同步工具类之 CountDownLatch

CountDownLatch 是一个同步工具类,它可以让一个或多个线程处于等待状态,直到其它的线程执行完毕再执行。

CountDownLatch 使用一个给定的计数值初始化,调用countDown()方法会使计数值减1,处于等待状态的方法在计数值变为0前一直阻塞,当计数值变为0时所有处于等待状态的线程会被释放,这个过程是一次性的,计数值不能被重置。如果需要重置计数值循环这个过程,可以考虑使用CyclicBarrier.

CountDownLatch 作为一个同步工具类可以被用作多种目的。比如将初始计数值设置为1就像设置了一个开关或者一扇门,所有线程调用await()方法在这扇门处处于等待状态,当一个线程调用countDown()方法后,计数值变为0,门会被打开,所有处于等待状态的线程开始执行。将初始值设置为N,可以让一个线程处于等待状态,等待N个线程完成后,或者某个动作被执行N次后再开始执行。像下面的例子一样:

class Driver { 
   void main() throws InterruptedException {
     CountDownLatch startSignal = new CountDownLatch(1);
     CountDownLatch doneSignal = new CountDownLatch(N);

     for (int i = 0; i < N; ++i) // create and start threads
       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            //所有Worker线程都处于等待状态,只执行doSomethingElse() 
     startSignal.countDown();      //准许所有Worker线程开始执行 
     doSomethingElse();
     doneSignal.await();           //等待所有Worker线程执行完毕 
   }
 }

 class Worker implements Runnable {
   private final CountDownLatch startSignal;
   private final CountDownLatch doneSignal;
   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
      this.startSignal = startSignal;
      this.doneSignal = doneSignal;
   }
   public void run() {
      try {
        startSignal.await(); //所有Worker线程执行到这里变为等待状态,在 startSignal.countDown()调用后继续执行
        doWork();
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }

另一个典型的用法就是将一个问题分解成多个线程来执行,主线程等待所有的子线程执行完毕后,主线程再继续执行。

class Driver2 { 
   void main() throws InterruptedException {
     CountDownLatch doneSignal = new CountDownLatch(N);
     Executor e = ...

     for (int i = 0; i < N; ++i) //启动多个子线程来处理问题 
       e.execute(new WorkerRunnable(doneSignal, i));

     doneSignal.await();           //等待所有子线程处理完毕 
	 doSomethingElse();
   }
 }

 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() {
      try {
        doWork(i);
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值