美文网首页JUC
CountDownLatch | 译

CountDownLatch | 译

作者: zlzl_ | 来源:发表于2022-10-31 23:44 被阅读0次

    https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html

    Class CountDownLatch

    java.util.concurrent.CountDownLatch
    public class CountDownLatch extends Object

    一种同步辅助,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。
    CountDownLatch 使用给定的计数进行初始化。由于调用了 countDown() 方法,await 方法会一直阻塞,直到当前计数达到零,然后释放所有等待的线程,并且任何后续的 await 调用都会立即返回。这是一次性现象——计数无法重置。如果您需要重置计数的版本,请考虑使用 CyclicBarrier。

    CountDownLatch 是一种多功能同步工具,可用于多种用途。使用计数 1 初始化的 CountDownLatch 用作简单的开/关锁存器或门:所有调用 await 的线程在门处等待,直到它被调用 countDown() 的线程打开。初始化为 N 的 CountDownLatch 可用于使一个线程等待,直到 N 个线程完成某个动作,或者某个动作已完成 N 次。

    CountDownLatch 的一个有用属性是它不需要调用 countDown 的线程在继续之前等待计数达到零,它只是阻止任何线程继续等待,直到所有线程都可以通过。

    示例用法:这是一对类,其中一组工作线程使用两个倒计时锁存器:

    第一个是启动信号,它阻止任何工人继续前进,直到司机准备好让他们继续前进;
    第二个是完成信号,允许驱动程序等待所有工作人员完成。

     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() { ... }
     }
    
    

    另一个典型的用法是将一个问题分成 N 个部分,用一个 Runnable 描述每个部分,该 Runnable 执行该部分并在锁存器上倒计时,并将所有 Runnables 排队到一个 Executor。 当所有子部分都完成后,协调线程就可以通过await了。 (当线程必须以这种方式重复倒计时时,请改用 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() { ... }
     }
    
    

    内存一致性影响:在计数达到零之前,线程中的操作在调用 countDown() 之前发生在从另一个线程中的相应 await() 成功返回之后的操作。

    Method Detail

    public void await() throws InterruptedException

    使当前线程等待直到锁存器倒计时到零,除非线程被中断。
    如果当前计数为零,则此方法立即返回。

    如果当前计数大于零,则当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下两种情况之一:

    • 由于调用了 countDown() 方法,计数达到零; 或者
    • 其他一些线程中断当前线程。
      如果当前线程:
    • 在进入此方法时设置其中断状态; 或者
    • 等待时被打断,
      然后抛出 InterruptedException 并清除当前线程的中断状态。

    public boolean await(long timeout, TimeUnit unit) throws InterruptedException

    使当前线程等待直到锁存器倒计时到零,除非线程被中断,或者指定的等待时间已过。
    如果当前计数为零,则此方法立即返回值 true。

    如果当前计数大于零,则当前线程出于线程调度目的而被禁用并处于休眠状态,直到发生以下三种情况之一:

    • 由于调用了 countDown() 方法,计数达到零; 或者
    • 其他一些线程中断当前线程; 或者
    • 指定的等待时间已过。
      如果计数达到零,则该方法返回值 true。
      如果当前线程:
    • 在进入此方法时设置其中断状态; 或者
    • 等待时被打断,
      然后抛出 InterruptedException 并清除当前线程的中断状态。
      如果经过指定的等待时间,则返回值 false。 如果时间小于或等于零,则该方法根本不会等待。
      Returns: 如果计数达到零,则返回 true;如果在计数达到零之前经过了等待时间,则返回 false

    public void countDown()

    减少锁存器的计数,如果计数达到零,则释放所有等待线程。
    如果当前计数大于零,则递减。 如果新计数为零,则重新启用所有等待线程以进行线程调度。

    如果当前计数为零,则不会发生任何事情。

    public long getCount()

    返回当前计数。
    此方法通常用于调试和测试目的。

    相关文章

      网友评论

        本文标题:CountDownLatch | 译

        本文链接:https://www.haomeiwen.com/subject/gwjltdtx.html