有人能帮助我理解什么是Java CountDownLatch以及什么时候使用它吗?
我不太清楚这个项目是怎么运作的。据我所知,这三个线程同时开始,每个线程将在3000ms后调用CountDownLatch。所以倒数会一个一个递减。锁存变为零后,程序打印“完成”。也许我理解的方式是错误的。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Processor implements Runnable {
private CountDownLatch latch;
public Processor(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("Started.");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}
// -----------------------------------------------------
public class App {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3); // coundown from 3 to 0
ExecutorService executor = Executors.newFixedThreadPool(3); // 3 Threads in pool
for(int i=0; i < 3; i++) {
executor.submit(new Processor(latch)); // ref to latch. each time call new Processes latch will count down by 1
}
try {
latch.await(); // wait until latch counted down to 0
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Completed.");
}
}
如果你在调用latch.countDown()后添加一些调试,这可能会帮助你更好地理解它的行为。
latch.countDown();
System.out.println("DONE "+this.latch); // Add this debug
输出将显示Count正在递减。这个“计数”实际上是你启动的可运行任务(处理器对象)的数量,其中countDown()没有被调用,因此在主线程调用latch.await()时被阻塞。
DONE java.util.concurrent.CountDownLatch@70e69696[Count = 2]
DONE java.util.concurrent.CountDownLatch@70e69696[Count = 1]
DONE java.util.concurrent.CountDownLatch@70e69696[Count = 0]
来自oracle关于CountDownLatch的文档:
一种同步辅助工具,允许一个或多个线程等待在其他线程中执行的一组操作完成。
CountDownLatch使用给定的计数进行初始化。由于调用了countDown()方法,await方法阻塞直到当前计数为零,在此之后所有等待的线程都被释放,并且await的任何后续调用立即返回。这是一个一次性现象——计数不能重置。
CountDownLatch是一种通用的同步工具,可用于许多目的。
初始化为1的CountDownLatch用作简单的开/关锁存器或门:所有调用await的线程都在门处等待,直到由调用countDown()的线程打开。
初始化为N的CountDownLatch可用于使一个线程等待到N个线程完成某个操作,或者某个操作已完成N次。
public void await()
throws InterruptedException
导致当前线程等待,直到锁存器计数到零,除非线程被中断。
如果当前计数为零,则此方法立即返回。
public void countDown()
减少锁存器的计数,如果计数为零,则释放所有等待线程。
如果当前计数大于零,则递减。如果新的计数为零,则所有等待的线程都将重新启用以进行线程调度。
解释你的例子。
You have set count as 3 for latch variable
CountDownLatch latch = new CountDownLatch(3);
You have passed this shared latch to Worker thread : Processor
Three Runnable instances of Processor have been submitted to ExecutorService executor
Main thread ( App ) is waiting for count to become zero with below statement
latch.await();
Processor thread sleeps for 3 seconds and then it decrements count value with latch.countDown()
First Process instance will change latch count as 2 after it's completion due to latch.countDown().
Second Process instance will change latch count as 1 after it's completion due to latch.countDown().
Third Process instance will change latch count as 0 after it's completion due to latch.countDown().
Zero count on latch causes main thread App to come out from await
App program prints this output now : Completed