CountDownLatch知识图谱:
面试题详解:
- 调用countDown方法时,线程也会阻塞吗?
- 如果已知的线程一直未准备就绪,如何避免调用await()方法的线程一直等待?
- CountDownLatch的实现原理是什么?
代码实例:
package com.springboot.thread;
import java.util.concurrent.CountDownLatch;
public class ThreadCommunication3 {
/*设置需要等待的线程的数量*/
private CountDownLatch countDownLatch = new CountDownLatch(3);/*eg:一个教练等待三个运动员准备完毕*/
/*运动员方法,由运动员线程调用*/
public void racer(){
/*获取当运动员的名称*/
String name = Thread.currentThread().getName();
System.out.println(name+"正在准备...");
/*线程休眠2秒,模拟运动员的准备过程*/
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"准备完毕!");
countDownLatch.countDown();
}
/*教练方法,由教练线程调用*/
public void coach(){
/*获取教练线程的名称*/
String name = Thread.currentThread().getName();
/*教练等待运动员准备*/
System.out.println(name+"等待运动员准备....");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
/*所有运动员就绪开始训练*/
System.out.println("运动员准备完毕"+name+"开始训练");
}
public static void main(String[] args) {
final ThreadCommunication3 threadCommunication3 = new ThreadCommunication3();
Thread racer1 = new Thread("racer1"){
@Override
public void run() {
threadCommunication3.racer();
}
};
Thread racer2 = new Thread("racer2"){
@Override
public void run() {
threadCommunication3.racer();
}
};
Thread racer3 = new Thread("racer3"){
@Override
public void run() {
threadCommunication3.racer();
}
};
Thread coach = new Thread("coach"){
@Override
public void run() {
threadCommunication3.coach();
}
};
coach.start();
racer1.start();
racer2.start();
racer3.start();
}
}
/*
CountDownLatch是一个计数器闭锁,通过它可以完成类似于阻塞当前线程的功能,
即:一个线程或多个线程一直等待,直到其他线程执行的操作完成。
CountDownLatch用一个给定的计数器来初始化,该计数器的操作是原子操作,
即同时只能有一个线程去操作该计数器。调用该类await方法的线程会一直处于阻塞状态,
直到其他线程调用countDown方法使当前计数器的值变为零,每次调用countDown计数器的值减1。
当计数器值减至零时,所有因调用await()方法而处于等待状态的线程就会继续往下执行。
*/
运行结果:
coach等待运动员准备....
racer3正在准备...
racer2正在准备...
racer1正在准备...
racer3准备完毕!
racer1准备完毕!
racer2准备完毕!
运动员准备完毕coach开始训练
原理图: