前言
这部分文章算是填坑文,涉及的内容的非常基础,比较适合刚接触JAVA的早鸟。顺便会在篇末更新leecode进度,算是给自己立flag,让网友来监督我刷lc,嘿。
什么是CountDownLatch
CountDownLatch 常译为闭锁,是JUC包中的线程同步工具之一。理解这个工具其实很简单,只要把CountDownLatch拆成CountDown和Latch两部分。Latch体现的是它的功能,类似于一个门闩,只有当门闩打开时线程才能通过;而CountDown则是门闩打开的钥匙(开锁条件),通过计数的方式来实现的钥匙,只有当内置计数为0时,条件成立,钥匙拿到才能把门闩打开。
CountDownLatch是使用AQS来实现的,AQS即 Abstract Queued Synchronizer,很多JUC中的同步工具都是用AQS来实现的,先过个眼熟,后面文章再专门来讲AQS源码。
使用场景
讲完CountDownLatch是什么后,来看看它最常用的两种场景。
场景一,让线程在同一个时间点开始执行
先上code
public static void startLatchDemo() {
CountDownLatch latch = new CountDownLatch(1);
// thread 1
new Thread(new Runnable(){
@Override
public void run() {
try{
latch.await();
// doSomething();
} catch(InterruptedException exception){
exception.printStackTrace();
}
}
}).start();
// thread 2
new Thread(new Runnable(){
@Override
public void run() {
try{
latch.await();
// doSomething();
} catch(InterruptedException exception){
exception.printStackTrace();
}
}
}
).start();
latch.countDown();
}
- CountDownLatch创建时参数为1(思考下这里为什么是1,下面会讲到)
- 在创建好要同时执行的线程后,在他们的执行方法之前调用await()方法进行等待,等待CountDownLatch的计数变为0
- 在主线程上调用countDown()方法,这时便会将CountDownLatch的计数设置为0,这就是为什么创建时要设置为1,因为触发执行的线程只有1个,门就会打开,之前等待的线程就会同时开始执行
场景二,监控所有线程执行结束
同样先上code
public static void doneLatchDemo() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(2);
// thread 1
new Thread(new Runnable(){
@Override
public void run() {
// doSomething();
latch.countDown();
}
}).start();
// thread 2
new Thread(new Runnable(){
@Override
public void run() {
// doSomething();
latch.countDown();
}
}).start();
latch.await();
// doSomethingAfterThreadsDone()
}
- CountDownLatch构建时,这次我们要传入N,这个N等于要监控的线程数量,本例中是2
- 这时我们在两个需要监控的线程执行完各自任务后调用CountDownLatch的countDown()方法
- 在主线程上我们调用CountDownLatch的await()方法,等待CountDownLatch的计数变为0,即监控的线程都完成任务并触发了countDown()方法,当条件成立后主线程便可继续执行,这里我们可以将监控的线程执行结果在这个线程上进行汇总应用。
这个系列的第一个坑就这样填完了,笔者力求用最简单的语言来讲一个抽象的东西,不是用另一个抽象的东西来解释。
后续会出JUC一系列填坑文,如果喜欢可以持续关注。如果有不清楚或者我写的不对的地方欢迎讨论。