之前開(kāi)發(fā)遇到一個(gè)場(chǎng)景,需要開(kāi)啟多線程上傳圖片到阿里云,將所以圖片上傳完成后柱蟀,將圖片地址一起提交到后端。那么這里就需要監(jiān)聽(tīng)這些多線程是否所有都執(zhí)行完成蚜厉。之前做的是用AtomicInteger來(lái)計(jì)數(shù)长已,每執(zhí)行完一個(gè)線程,將這個(gè)變量+1弯囊,然后判斷該值是否等于啟動(dòng)的線程數(shù)痰哨,如果相等了,則表明所有線程執(zhí)行完畢匾嘱。那么這種場(chǎng)景還可以直接用CountDownLatch來(lái)進(jìn)行實(shí)現(xiàn)斤斧。
CountDownLatch是一個(gè)同步工具類,它通過(guò)一個(gè)計(jì)數(shù)器來(lái)實(shí)現(xiàn)的,初始值為線程的數(shù)量霎烙。每當(dāng)一個(gè)線程完成了自己的任務(wù),計(jì)數(shù)器的值就相應(yīng)得減1撬讽。當(dāng)計(jì)數(shù)器到達(dá)0時(shí),表示所有的線程都已執(zhí)行完畢,然后在等待的線程就可以恢復(fù)執(zhí)行任務(wù)蕊连。
方法詳解
CountDownLatch(int count):count為計(jì)數(shù)器的初始值(一般需要多少個(gè)線程執(zhí)行,count就設(shè)為幾)游昼。
countDown(): 每調(diào)用一次計(jì)數(shù)器值-1甘苍,直到count被減為0,代表所有線程全部執(zhí)行完畢烘豌。
getCount():獲取當(dāng)前計(jì)數(shù)器的值载庭。
await(): 等待計(jì)數(shù)器變?yōu)?,即等待所有異步線程執(zhí)行完畢廊佩。
CountDownLatch的使用場(chǎng)景
1.某一線程在開(kāi)始運(yùn)行前等待n個(gè)線程執(zhí)行完畢囚聚。
2.實(shí)現(xiàn)多個(gè)線程開(kāi)始執(zhí)行任務(wù)的最大并行性。
實(shí)例:業(yè)務(wù)線程等待子線程初始化執(zhí)行完成再執(zhí)行
public class CountDownLatchUtil {
private static CountDownLatch countDownLatch = new CountDownLatch(6);
public static void main(String args[]) {
for (int i=0;i<5;i++) {
Thread thread = new Thread(new InitThread());
thread.start();
}
Thread thread = new Thread(new BusiThread());
thread.start();
}
private static class InitThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":執(zhí)行初始化任務(wù)");
countDownLatch.countDown();
}
}
private static class BusiThread implements Runnable {
@Override
public void run() {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("BusiThread" + "執(zhí)行業(yè)務(wù)任務(wù)");
}
}
}
創(chuàng)建5個(gè)子線程執(zhí)行run标锄,run方法中調(diào)用countDown方法進(jìn)行計(jì)數(shù)-1顽铸。同時(shí)創(chuàng)建BusiThread任務(wù),在run中調(diào)用await料皇,等待計(jì)數(shù)為0谓松,再執(zhí)行自己的業(yè)務(wù)任務(wù)。