无论你对CountDownLatch的认知是通过看资料还是看博客,很多人都会存在一些误区。现在我也是站在巨人(某些大牛)的肩膀上去总结下这些误区,并把CountDownLatch的含义及用法仔细的演示一遍。
1、常见误区
- 误区一:CountDownLatch的计数器的值就是实际要控制的线程数。
- 误区二:每个线程中CountDownLatch的扣减点只有一个。
- 误区三:使用countDown()扣减后,当前线程就结束了。
- 误区四:使用await() 等待的线程只有一个。
2、直接贴代码,然后逐个解释
import java.util.concurrent.CountDownLatch;
/**
* 演示CountDownLatch的使用
* 用法讲解:
* 1. 声明一个CountDownLatch对象,给一个初始化的线程数,线程数可以比实际线程数要多
* 2. countDown()方法是指在当前线程执行完后,给计数器减1而已,不会阻塞其他线程,且同一个线程完全可以扣减2次
* 3. 执行完countDown()后不一定就要关闭当前线程,也就是说当前线程执行完countDown()后还可以再继续执行
* 4. CountDownLatch的await()方法是指等待CountDownLatch的countDown()扣减为0后再被唤醒执行,也可以是多个线程在await()等待
*/
public class UseCountDownLatch {
// CountDownLatch构造参数传一个整数值
// 这个数可以定义的比实际线程数要多,不一定是一样的,同一个线程完全可以扣减2次
static CountDownLatch latch = new CountDownLatch(8);
private static class InitThread implements Runnable {
@Override
public void run() {
System.out.println("Thread_" + Thread.currentThread().getId()
+ " ready init work......");
latch.countDown();
// System.out.println(Thread.currentThread().getName() + "...." + latch.getCount());
for (int i = 0; i < 2; i++) {
System.out.println("Thread_" + Thread.currentThread().getId()
+ " ........continue do its work");
}
}
}
// 业务线程要等其他线程执行完后,才被唤醒然后执行
// 结果你会看到BusiThread的线程全都在最后才执行,印证了这一点
private static class BusiThread implements Runnable {
@Override
public void run() {
try {
// await()表示当前线程被CountDownLatch命令等待
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 3; i++) {
System.out.println("BusiThread_" + Thread.currentThread().getId()
+ " do business-----");
}
}
}
public static void main(String[] args) throws InterruptedException {
// 1. 先(使用匿名内部类的方式)创建一个线程
new Thread(new Runnable() {
@Override
public void run() {
SleepTools.ms(1);
System.out.println("Thread_" + Thread.currentThread().getId()
+ " ready init work step 1st......");
latch.countDown();
System.out.println("begin step 2nd.......");
SleepTools.ms(1);
System.out.println("Thread_" + Thread.currentThread().getId()
+ " ready init work step 2nd......");
latch.countDown();
}
}).start();
// 2. 再创建一个业务线程,该线程处于等待状态,先不执行
new Thread(new BusiThread()).start();
// 3. 创建3个初始化线程,每个线程执行一次countDown()
for (int i = 0; i <= 3; i++) {
Thread thread = new Thread(new InitThread());
thread.start();
}
// 4. CountDownLatch执行阻塞方法
latch.await();
System.out.println("Main do ites work........");
// 1.2.3.4 不代表任何,只是便于分析
}
}
执行的结果:
Thread_13 ready init work......
Thread_15 ready init work......
Thread_14 ready init work......
Thread_15 ........continue do its work
Thread_13 ........continue do its work
Thread_16 ready init work......
Thread_13 ........continue do its work
Thread_15 ........continue do its work
Thread_14 ........continue do its work
Thread_16 ........continue do its work
Thread_14 ........continue do its work
Thread_16 ........continue do its work
Thread_11 ready init work step 1st......
begin step 2nd.......
Thread_11 ready init work step 2nd......
Main do ites work........
BusiThread_12 do business-----
BusiThread_12 do business-----
BusiThread_12 do business-----
3、结论
(在代码类上的注释中)。