1. CountDownLatch 是什么?
從這個類的字面意思來入手衡蚂,CountDown 是倒計時的意思棚愤,Latch 是門栓的意思,加起來的意思就是一個倒計時的門栓戚啥。
它其實是作用于線程當(dāng)中的奋单,它就像一個門栓,一開始是關(guān)閉的猫十,所有希望通過該門的線程都需要等待览濒,然后開始倒計時,當(dāng)?shù)褂嫊r一到拖云,等待的所有線程都可以通過贷笛。
要注意的是,它是一次性的宙项,打開之后就不能關(guān)上了昨忆。
2. 怎么使用 CountDownLatch
2.1 構(gòu)造方法
public CountDownLatch(int count)
解釋:
- count 就是需要等待的線程數(shù)量
2.2 重要方法
// 調(diào)用此方法的線程會被阻塞,直到 CountDownLatch 的 count 為 0
public void await() throws InterruptedException
// 和上面的 await() 作用基本一致杉允,只是可以設(shè)置一個最長等待時間
public boolean await(long timeout, TimeUnit unit) throws InterruptedException
// 會將 count 減 1邑贴,直至為 0
public void countDown()
2.3 基本使用
2.3.1 需求
現(xiàn)在實現(xiàn)主線程等待其他線程的任務(wù)完成之后,才繼續(xù)執(zhí)行的代碼叔磷。
2.3.2 代碼實現(xiàn)
public class CountDownLatchDemo {
static class TaskThread extends Thread {
CountDownLatch latch;
public TaskThread(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(getName() + " Task is Done");
latch.countDown();
}
}
}
public static void main(String[] args) throws InterruptedException {
int threadNum = 10;
CountDownLatch latch = new CountDownLatch(threadNum);
for(int i = 0; i < threadNum; i++) {
TaskThread task = new TaskThread(latch);
task.start();
}
System.out.println("Task Start!");
latch.await();
System.out.println("All Task is Done!");
}
}
代碼解釋:
- 設(shè)置 CountDownLatch 的等待線程數(shù)為 10
- 開啟 10 個線程拢驾,每個線程都會睡眠 1 秒,睡眠結(jié)束后就會調(diào)用 CountDownLatch 的 countDown() 方法
- 主線程調(diào)用 CountDownLatch 的 await() 方法改基,所以會開始阻塞繁疤,直到 CountDownLatch 的 count 為 0 才繼續(xù)執(zhí)行
打印結(jié)果:
Task Start!
Thread-1 Task is Done
Thread-5 Task is Done
Thread-8 Task is Done
Thread-9 Task is Done
Thread-2 Task is Done
Thread-7 Task is Done
Thread-6 Task is Done
Thread-4 Task is Done
Thread-3 Task is Done
Thread-0 Task is Done
All Task is Done!
3. CountDownLatch 使用場景
3.1 同時啟動多個線程
如果想同時啟動多個線程,實現(xiàn)最大的并行性秕狰,就可以使用 CountDownLatch稠腊。稍微修改上面的例子代碼,代碼如下:
public class CountDownLatchDemo {
static class TaskThread extends Thread {
CountDownLatch latch;
public TaskThread(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
latch.await();
System.out.println(getName() + " start " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
int threadNum = 10;
CountDownLatch latch = new CountDownLatch(1);
for(int i = 0; i < threadNum; i++) {
TaskThread task = new TaskThread(latch);
task.start();
}
Thread.sleep(1000);
latch.countDown();
}
}
代碼解釋:
- 設(shè)置 CountDownLatch 等待線程數(shù)為 1
- 開啟 10 個線程鸣哀,每個線程都會調(diào)用 CountDownLatch 的 await() 方法架忌,這樣每個線程都會被阻塞
- 主線程休眠 1 秒后,調(diào)用 CountDownLatch 的 countDown() 方法我衬,調(diào)用后就會喚醒所有等待的線程叹放,所有等待的線程就會同時執(zhí)行
打印結(jié)果:
Thread-1 start 1535987605552
Thread-3 start 1535987605552
Thread-2 start 1535987605552
Thread-0 start 1535987605552
Thread-6 start 1535987605552
Thread-5 start 1535987605552
Thread-8 start 1535987605552
Thread-4 start 1535987605552
Thread-9 start 1535987605552
Thread-7 start 1535987605552
3.2 等待多個線程完成各自任務(wù)后再開始執(zhí)行自己的任務(wù)
這個例子在 2.3 節(jié)已經(jīng)說過了,這里就不再細(xì)說了挠羔。
參考文章: