同步工具类之CountDownLatch
2017-01-09 本文已影响15人
evil_ice
一,CountDownLatch概述
CountDownLatch是一种灵活的闭锁实现.闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态.闭锁的作用相当于一扇门----在闭锁到达结束状态之前,这扇门一直是关闭的,并没有任何线程能通过,当到达结束状态时,这扇门会打开并允许所有的线程通过.当闭锁达到结束状态后,将不会再改变状态因此这扇门将永远保持打开状态.
二,CountDownLatch使用场景
- CountDownLatch 是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。
public class Test {
public static void main(String[] args){
Test test = new Test();
try {
test.timeTasks(10, new Runnable(){
@Override
public void run() {
System.out.println("abcd");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public long timeTasks(int nThreads, final Runnable task) throws InterruptedException{
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(nThreads);
for(int i=0; i<nThreads; i++){
Thread t = new Thread(){
@Override
public void run() {
super.run();
try{
startGate.await();
try{
task.run();
}finally{
endGate.countDown();
}
}catch(Exception e){
}
}
};
t.start();
}
long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end - start;
}
}
- 另一种典型用法是,将一个问题分成 N 个部分,用执行每个部分并让锁存器倒计数的 Runnable 来描述每个部分,然后将所有 Runnable 加入到 Executor 队列。当所有的子部分完成后,协调线程就能够通过 await。
用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。
public class Test {
private static final int N = 10;
public static void main(String[] args) {
CountDownLatch doneSignal = new CountDownLatch(N);
Executor executor = Executors.newCachedThreadPool();
for (int i = 0; i < N; ++i) {
executor.execute(new WorkerRunnable(doneSignal, i));
}
try {
doneSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
System.out.println(Thread.currentThread().getName()+" "+"前面的N个任务执行完毕了");
}
}
}
class WorkerRunnable implements Runnable {
private final CountDownLatch doneSignal;
private final int i;
WorkerRunnable(CountDownLatch doneSignal, int i) {
this.doneSignal = doneSignal;
this.i = i;
}
public void run() {
doWork(i);
doneSignal.countDown();
}
void doWork(int i) {
System.out.println(Thread.currentThread().getName() + " i=" + i);
}
}
参考
1,<<java并发编程实战>>
2,jdk文档