Class CountDownLatch

Class CountDownLatch


描述

  • 它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成为止。

  • 使用给定的count初始化CountDownLatch。

  • await方法阻塞,直到调用countDown()方法使当前计数为零

  • 之后释放所有等待线程,并立即返回任何后续的await调用

  • 这是一种一次性现象——计数无法重置。如果需要重新设置计数的版本,请考虑使用CyclicBarrier。

  • CountDownLatch是一种通用的同步工具,可以用于多种用途。count为1时初始化的CountDownLatch用作简单的on/off 开关:所有调用wait的线程都在此处等待,直到调用countDown()的线程打开它。一个初始化为N的CountDownLatch可以用来让一个线程等待,直到N个线程完成某个动作,或者某个动作已经完成N次。

  • CountDownLatch的一个有用的特性是,它不需要调用倒计时的线程等待计数达到零才继续,它只是防止任何线程继续等待,直到所有线程都通过。

使用样例

  1. 下面是两个类,其中一组工作线程使用两个倒计时锁存器:

    第一个是启动信号,它阻止任何worker继续工作,直到驱动程序准备好让它们继续工作;

    第二个是完成信号,允许worker等待,直到所有的工人完成。

     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();            // don't let run yet
         startSignal.countDown();      // let all threads proceed
         doSomethingElse();
         doneSignal.await();           // wait for all to finish
       }
     }
    
     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();
           doWork();
           doneSignal.countDown();
         } catch (InterruptedException ex) {} // return;
       }
    
       void doWork() { ... }
     }
    
  2. 另一种典型的用法是将一个问题分成N个部分,用一个Runnable来描述每个部分,该Runnable执行该部分并在锁存器上计数,然后将所有Runnables排队给一个执行器。当所有子部件完成后,协调线程将能够通过wait。(当线程必须以这种方式重复计数时,使用CyclicBarrier。)

    class Driver2 { // ...
       void main() throws InterruptedException {
         CountDownLatch doneSignal = new CountDownLatch(N);
         Executor e = ...
    
         for (int i = 0; i < N; ++i) // create and start threads
           e.execute(new WorkerRunnable(doneSignal, i));
    
         doneSignal.await();           // wait for all to finish
       }
     }
    
     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() { ... }
     }
    

你可能感兴趣的:(java)