Java CountDownLatch –一个不错的同步助手
Java CountDownLatch类是Concurrency API的一部分。
它允许我们创建一个同步,其中一个线程等待直到倒数为0。
当我们希望一个线程在有限数量的其他线程上等待完成处理时,这很有用。
CountDownLatch如何工作?
使用给定的计数创建CountDownLatch实例。
当线程调用CountDownLatch await()方法时,它将等待直到计数为0。
完成后,其他线程有责任调用CountDownLatch countDown()方法。
每次调用countDown()方法都会使计数值减少1。当所有其他线程都调用countDown()方法时,计数变为0,并且由于await()而等待的线程将开始执行。
count的值无法重置,因此一旦CountDownLatch工作完成,我们将无法重用同一实例。
进一步调用await()将不会导致线程阻塞。
Java CountDownLatch示例
让我们看一个多线程应用程序中CountDownLatch的简单示例。
package com.theitroad.concurrency; import java.util.Random; import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) { CountDownLatch latch = new CountDownLatch(3); Random random = new Random(); WorkerThread wt1 = new WorkerThread(latch, random.nextInt(5000)); WorkerThread wt2 = new WorkerThread(latch, random.nextInt(5000)); WorkerThread wt3 = new WorkerThread(latch, random.nextInt(5000)); new Thread(wt1, "WT-11").start(); new Thread(wt2, "WT-22").start(); new Thread(wt3, "WT-33").start(); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Finishing the Main Method"); } } class WorkerThread implements Runnable { private CountDownLatch latch; private int delay; public WorkerThread(CountDownLatch latch, int delay) { this.latch = latch; this.delay = delay; } @Override public void run() { String name = Thread.currentThread().getName(); int delay = this.delay; System.out.println(name + " sleeping for " + delay + " milliseconds."); try { Thread.sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } this.latch.countDown(); System.out.println(name + " finished"); } }
我们有3个工作线程,我们希望我们的主线程等待,直到全部完成。
因此,我们使用count 3初始化CountDownLatch。在辅助线程中,我们在CountDownLatch实例上调用countDown()方法。
因此,当所有3个工作线程都完成处理后,计数将变为0,并且由于await()而等待的主线程将开始执行。主线程由于CountDownLatch await()调用而被阻塞。
一旦计数变为0,它将开始执行。在CountDownLatch同步机制的帮助下,我们确保在完成主线程之前执行所有辅助线程。
上述程序的可能输出如下:
WT-33 sleeping for 2962 milliseconds. WT-22 sleeping for 3874 milliseconds. WT-11 sleeping for 1746 milliseconds. WT-11 finished WT-33 finished WT-22 finished Finishing the Main Method
CountDownLatch await()
有两种版本的await()方法。
await():无限期地等待计数变为0,除非线程被中断。
await(长超时,TimeUnit单位):使用给定的超时值等待计数变为0。
如果发生超时,则该方法停止阻塞并返回false。
CountDownLatch与CyclicBarrier
CountDownLatch提供了一种机制来等待计数变为0,而CyclicBarrier提供了一种机制来创建每个线程await()调用都会到达的公共屏障"计数"。
CountDownLatch操作是不可逆的,一旦计数为0,对await()的任何进一步调用都不会阻塞线程。
就像CyclicBarrier所提示的那样,它本质上是循环的,并且在释放等待线程之后,屏障会再次使用。当我们要等待一组特定的线程执行时,CountDownLatch很有用。
当我们有多个线程并且仅在执行一定数量的线程时才等待时,CyclicBarrier很有用。