开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情
简介
CountDownLatch 是通过一个计数器来实现的,计数器的初始值为 线程的数量 。每当一个线程执行完成后,计数器的值 -1 ,当值为 0 时,表示所有线程执行完毕。
计数器count是闭锁需要等待的线程数量,只能被设置一次,且CountDownLatch没有提供任何机制去重新设置计数器count。
与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
其他N个线程必须引用CountDownLatch闭锁对象,因为它们需要通知CountDownLatch对象,它们各自完成了任务;这种通知机制是通过CountDownLatch.countDown()方法来完成的;每调用一次,count的值就减1,因此当N个线程都调用这个方法,count的值就等于0,然后主线程就可以通过await()方法,恢复执行自己的任务。
使用场景
1.执行某个任务前完成各自任务,比如在返回前端数据前,一些多线程任务必须完成。
2.死锁检测:用N个线程去访问共享资源,在每个测试阶段线程数量不同,并尝试产生死锁。
使用例子
作为场景第一种 - 执行某个任务前完成各自任务
代码示例
main 方法
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
new Thread(new Worker(startSignal, doneSignal)).start();
}
System.out.println("zhunbei bobo");
startSignal.countDown();
System.out.println("henhen bobo");
doneSignal.await();
System.out.println("bobo wanbi");
}
}
线程方法
public class Worker implements Runnable{
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
@Override
public void run() {
try {
//调用await()方法的线程会被挂起,等待直到count值为0再继续执行。
startSignal.await();
go();
//线程执行完毕 -1
doneSignal.countDown();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
void go() {
System.out.println("liuyi bobo !");
}
}
输出结果
zhunbei bobo
henhen bobo
liuyi bobo !
liuyi bobo !
liuyi bobo !
liuyi bobo !
liuyi bobo !
liuyi bobo !
liuyi bobo !
liuyi bobo !
liuyi bobo !
liuyi bobo !
bobo wanbi
可见主线程在 await() 后的代码,需要等待 work 线程方法全部执行完毕后,才执行。
好了,今日学习到这里了,有点太晚了,另一个场景的代码例子我们明天再实现,晚安。