1、背景
一个平常面试高频次会被提及的东东,属于线程之间的一种通信问题。
这里先提一个问题:有两个线程,第一个线程需要等待第二个线程执行完所有的任务之后,第一个线程才能继续执行,那咱们可以使用线程中的哪个机制能实现呢?很显然利用Thread.join()方法。但是还有一种场景是用Thread.join()解决不了的。
2、CountDownLatch使用情景
该情景是:启动了一个主服务,然后它下面会启动五个子服务,而当五个子服务都执行到一半的逻辑时【或者是特定条件成立时】则通知主服务可以继续往下执行了,而五个子服务没有执行到一半完成之前主服务只能等待。很明显这种业务场景用Thread.join()是没法实现的,因为join()是一定要等待指定线程都执行消亡了调用方才能继续往下执行
例子:
import java.util.concurrent.CountDownLatch;
import java.util.stream.IntStream;
public class MyTest1 {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(3);
IntStream.range(0, 3).forEach(i -> new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println("hello");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}).start());
System.out.println("启动子线程完毕!");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程执行完毕!");
}
}
方法分析
- 1、CountDownLatch countDownLatch = new CountDownLatch(3);
表示记数器值count的最大大小,必须调用countDown()方法的次数才会往下执行 - 2、public void await() throws InterruptedException { };
调用await()方法的线程会进入阻塞队列,它会等待直到count值为0才继续执行 - 3、public void countDown() { };
将count值减1,计数器count减为0时则不会再发生变化了,也就是说不会再继续减成负数了
内容分析
创建了3个新的线程,每个线程都有各自的执行代码,CountDownLatch初始设置记数器count为3,当调用 countDownLatch.await() 方法时,需要调用3次 countDownLatch.countDown() 方法才会继续执行下去,这里充分说明了3个新的线程并不需要全部都执行完,主线程才可以继续执行,而是3个新的线程执行到一定关键位置时,觉得可以了,主线程就可以继续执行了
输出
启动子线程完毕!
hello
hello
hello
主线程执行完毕!
网友评论