首页 > 代码库 > concurrent并发包之CountDownLatch

concurrent并发包之CountDownLatch

CountDownLatch实际上是一种闭锁实现。闭锁:是一种同步工具类,可以延迟线程的进度知道其到达终止状态——《Java并发编程实战》。这个怎么解释呢?简单来说,就是有1个线程需要等待其余10个线程都执行完毕后再执行,这个时候就可以使用闭锁,也即CountDownLatch(当然闭锁的实现并不止这一种)。关于对闭锁的详细解释请参考《Java并发编程实战》P79。

CountDownLatch中有一个计数器,该计数器通过构造方法传递,表示需要完成的工作。有两个主要的方法:countDown——表示计数器减1,再完成一个工作时调用此方法。await——表示唤醒,等待线程在执行方法前调用此方法,当计数器未为0(即还有工作尚未完成)时,被阻塞,当所有工作都已完成,计数器被减至0,此时等待线程才被唤醒以继续执行。

我们通过代码来实际感受一下CountDownLatch类API的使用。

首先有一个TaskThread任务线程,表示做好准备工作的线程。

 1 package countdownlatch;
 2 
 3 import java.util.concurrent.CountDownLatch;
 4 
 5 /**
 6  * Created by yulinfeng on 12/14/16.
 7  */
 8 public class TaskThread implements Runnable {
 9     private final CountDownLatch latch;
10 
11     public TaskThread(CountDownLatch latch){
12         this.latch = latch;
13     }
14 
15     @Override
16     public void run() {
17         try {
18             doWork();
19             latch.countDown();  //线程执行完这部分工作后,CountDownLatch的计数减1。
20         } catch (InterruptedException e) {
21             e.printStackTrace();
22         }
23     }
24 
25     private void doWork() throws InterruptedException{
26         System.out.println(Thread.currentThread().getName());
27         Thread.sleep(2000);  //休眠2s,模拟这部分工作的完成
28     }
29 }

接着是等待线程,即当所有的TaskThread完成各自的工作之后再执行此线程。

 1 package countdownlatch;
 2 
 3 import java.util.concurrent.CountDownLatch;
 4 
 5 /**
 6  * Created by yulinfeng on 12/14/16.
 7  */
 8 public class WaitThread implements Runnable{
 9     private final CountDownLatch latch;
10 
11     public WaitThread(CountDownLatch latch){
12         this.latch = latch;
13     }
14 
15     @Override
16     public void run() {
17         try {
18             System.out.println("Wait for other threads to execute!");   //就算CPU在未完成所有TaskThread进入到次线程,该线程也会因为CountDownLatch计数器未减至0而阻塞。
19             latch.await();  //直到CountDownLatch的计数器减至0(即表示所有的工作也完成)才继续执行,否则阻塞。
20             System.out.println("Other threads have already completed!");
21         } catch (InterruptedException e) {
22             e.printStackTrace();
23         }
24 
25     }
26 }

测试代码:

 1 package countdownlatch;
 2 
 3 import java.util.concurrent.CountDownLatch;
 4 import java.util.concurrent.ExecutorService;
 5 import java.util.concurrent.Executors;
 6 
 7 /**
 8  * Created by yulinfeng on 12/14/16.
 9  */
10 public class Test {
11 
12     public static void main(String[] args){
13         ExecutorService exec = Executors.newCachedThreadPool();
14         CountDownLatch latch = new CountDownLatch(100);     //所有线程必须共享一个CountDownLatch单例(这也是在另外两个线程中CountDownLatch定义为final不可变引用的原因),模拟有100个工作待完成。
15 
16         exec.execute(new WaitThread(latch));    //等待线程
17         for (int i = 0; i < 100; i++){
18             exec.execute(new TaskThread(latch));    //开启100个线程,模拟完成100个工作。
19         }
20 
21         exec.shutdown();
22     }
23 }

执行结果很好的诠释了CountDownLatch:

技术分享

技术分享

 

concurrent并发包之CountDownLatch