Java并發(fā)編程同步器CountDownLatch
CountDownLatch
在日常開發(fā)中經(jīng)常會(huì)遇到需要在主線程中開啟多個(gè)線程去并行執(zhí)行任務(wù),并且主線程需要等待所有子線程執(zhí)行完畢后再進(jìn)行匯總的場(chǎng)景。在 CountDownLatch 出現(xiàn)之前般都使用線程的join()方法來實(shí)現(xiàn)這一點(diǎn),但是 join 方法不夠靈活,不能夠滿足不同場(chǎng)景的需要,所以 JDK 開發(fā)組提供了 CountDownLatch 這個(gè)類,我們前面介紹的例子使用 CoumtDownLatch 會(huì)更優(yōu)雅。
使用CountDownLatch 的代碼如下:
package LockSupportTest;
import java.util.concurrent.CountDownLatch;
public class JoinCountDownLatch {
private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);
public static void main(String[] args) throws InterruptedException{
Thread threadOne = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("child threadOne over!");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}
});
Thread threadTwo = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("child threadOne over!");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}
});
threadOne.start();
threadTwo.start();
System.out.println("wait all child thread over!!!");
countDownLatch.await();
System.out.println("all child thread over!");
}
}

在如上代碼中,創(chuàng)建了一個(gè) CountDownLatch 實(shí)例,因?yàn)橛袃蓚€(gè)子線程所以構(gòu)造函數(shù)的傳參為2。主線程調(diào)用countDownLatch.await()方法后會(huì)被阻塞。子線程執(zhí)行完畢后調(diào)用 countDownLatch.countDown()方法讓 countDownLatch 內(nèi)部的計(jì)數(shù)器減1,所有子線程執(zhí)行完畢并調(diào)用 countDown()方法后計(jì)數(shù)器會(huì)變?yōu)?,這時(shí)候主線程的await()方法才會(huì)返回。其實(shí)上面的代碼還不夠優(yōu)雅,在項(xiàng)目實(shí)踐中一般都避免直接操作線程,而是使用 ExceutorService線程池來管理,使用ExcsuIwsnise時(shí)傳遞的參數(shù)是 Runable 或者 Callable對(duì)象,這時(shí)候你沒有辦法直接調(diào)用這些線程的join()方法,這就需要選擇使用CountDownLatch了。
將上面的代碼修改為:
package LockSupportTest;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class JoinCountDownLatch2 {
private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);
public static void main(String[] args) throws InterruptedException{
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("child threadOne over!");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("child threadTwo over!");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}
});
System.out.println("wait all child thread over!!!");
countDownLatch.await();
System.out.println("all child thread over!");
executorService.shutdown();
}
}

最后總結(jié)一下CountDownLatch與join()的區(qū)別。一個(gè)區(qū)別是,調(diào)用一個(gè)子線程的join()方法后,該線程會(huì)一直被阻塞直到子線程運(yùn)行完畢,而 CountDownLatch 則使用計(jì)數(shù)器來允許子線程運(yùn)行完畢或者在運(yùn)行中遞減計(jì)數(shù),也就是 CountDownLach 可以在子線程運(yùn)行的任何時(shí)候讓 await() 方法返回而不一定必須等到線程結(jié)東。另外,使用線程池來管理線程時(shí)一般都是直接添加 Runable 到線程池,這時(shí)候就沒有辦法再調(diào)用線程的 join 方法了,就是說 counDownLatch 相比 join 方法讓我們對(duì)線程同步有更靈活的控制。
到此這篇關(guān)于Java并發(fā)編程同步器CountDownLatch的文章就介紹到這了,更多相關(guān)Java CountDownLatch內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JVM 方法調(diào)用之動(dòng)態(tài)分派(詳解)
下面小編就為大家?guī)硪黄狫VM 方法調(diào)用之動(dòng)態(tài)分派(詳解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
Windows10系統(tǒng)下修改jar中的文件并重新打包成jar文件然后運(yùn)行的操作步驟
這篇文章主要介紹了Windows10系統(tǒng)下修改jar中的文件并重新打包成jar文件然后運(yùn)行的操作步驟,文中通過圖文結(jié)合的形式給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-08-08
IDEA插件之Mybatis Log plugin 破解及安裝方法
這篇文章主要介紹了IDEA插件之Mybatis Log plugin 破解方法及安裝方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
LambdaQueryWrapper與QueryWrapper的使用方式
這篇文章主要介紹了LambdaQueryWrapper與QueryWrapper的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
spring boot中interceptor攔截器未生效的解決
這篇文章主要介紹了spring boot中interceptor攔截器未生效的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
關(guān)于Java中攔截mybatis并輸出完整sql語句的方法
這篇文章主要介紹了關(guān)于Java中攔截mybatis并輸出完整sql語句的方法,假如項(xiàng)目中有很多很多的SQL我們不可能一一的去修改解決。這個(gè)時(shí)候我們就需要通過mybatis攔截SQL并且最終修改SQL,需要的朋友可以參考下2023-08-08
SpringBoot使用Redis的zset統(tǒng)計(jì)在線用戶信息
這篇文章主要介紹了SpringBoot使用Redis的zset統(tǒng)計(jì)在線用戶信息,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot框架,感興趣的朋友可以了解下2021-04-04

