Java詳解多線程協(xié)作作業(yè)之信號(hào)同步
一、信號(hào)同步
多線程很多時(shí)候是協(xié)作作業(yè)。比如4個(gè)線程對(duì)電商數(shù)據(jù)分季度統(tǒng)計(jì),統(tǒng)計(jì)完成之后,再匯總。如何知道4個(gè)線程都執(zhí)行完成呢,我們可以使用JDK1.5給我們提供的輔助類CountDownLatch(
減少計(jì)數(shù))、CyclicBarrier(循環(huán)柵欄)、Semaphore(信號(hào)燈)。
二、基于時(shí)間維度
1、CountDownLatch
多少個(gè)協(xié)作線程就初始化CountDownLatch的構(gòu)造參數(shù)是多少。
public static void main(String[] args) throws InterruptedException {
final int NUM=6;
//定義總數(shù)量;
CountDownLatch countDownLatch=new CountDownLatch(NUM);
for (int i = 0; i < NUM; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"線程,已執(zhí)行!");
//減少計(jì)數(shù)
countDownLatch.countDown();
},String.valueOf(i+1)).start();
}
//等待所有任務(wù)完成
countDownLatch.await();
System.out.println("所有線程任務(wù)已經(jīng)執(zhí)行完成!");
}
2、CyclicBarrier
與減少計(jì)數(shù)類似
public static void main(String[] args) {
final int NUM = 6;
//定義循環(huán)數(shù)量及循環(huán)完成后的任務(wù)(Runnable接口實(shí)現(xiàn));
CyclicBarrier cyclicBarrier = new CyclicBarrier(NUM, () -> {
System.out.println("所有線程任務(wù)已經(jīng)執(zhí)行完成!");
});
for (int i = 0; i < NUM; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"線程,已執(zhí)行!");
try {
//等待點(diǎn)或障礙點(diǎn),等待所有任務(wù)完成,
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
},String.valueOf(i+1)).start();
}
}
三、基于信號(hào)維度
Semaphore,線程與信號(hào)是m:n,其中m>=n。
import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/*信號(hào)燈
* 6個(gè)線程,搶占三個(gè)信號(hào)
* */
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore=new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(()->{
try {
//獲取信號(hào)
semaphore.acquire();
System.out.println("線程:"+Thread.currentThread().getName()+"----獲取信號(hào)");
int time = new Random().nextInt(5);
System.out.println(("線程:"+Thread.currentThread().getName()+"----休眠"+time+"s!"));
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
// 釋放信號(hào)
System.out.println("線程:"+Thread.currentThread().getName()+"---釋放信號(hào)");
semaphore.release();
}
},String.valueOf(i+1)).start();
}
}
}首先線程4、1、3獲取到信號(hào),線程1釋放信號(hào)后,線程2獲得信號(hào)。線程2、3釋放信號(hào)后,線程5、6獲得信號(hào)。

到此這篇關(guān)于Java詳解多線程協(xié)作作業(yè)之信號(hào)同步的文章就介紹到這了,更多相關(guān)Java信號(hào)同步內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
iOS socket網(wǎng)絡(luò)編程實(shí)例詳解
socket是一個(gè)針對(duì)TCP和UDP編程的接口,你可以借助它建立TCP連接等。這篇文章主要介紹了iOS socket網(wǎng)絡(luò)編程 ,需要的朋友可以參考下2017-03-03
Java實(shí)現(xiàn)的質(zhì)因數(shù)分解操作示例【基于遞歸算法】
這篇文章主要介紹了Java實(shí)現(xiàn)的質(zhì)因數(shù)分解操作,結(jié)合實(shí)例形式較為詳細(xì)的分析了Java基于遞歸算法實(shí)現(xiàn)針對(duì)整數(shù)的質(zhì)因數(shù)分解相關(guān)操作技巧,需要的朋友可以參考下2018-03-03
springboot組件初始化后的4種啟動(dòng)方式及常用方法
在Spring Boot中,您可以通過幾種方式在組件初始化后執(zhí)行啟動(dòng)任務(wù),下面小編給大家分享springboot組件初始化后的4種啟動(dòng)方式及常用方法,感興趣的朋友一起看看吧2024-06-06
RocketMQ?NameServer架構(gòu)設(shè)計(jì)啟動(dòng)流程
這篇文章主要為大家介紹了RocketMQ?NameServer架構(gòu)設(shè)計(jì)啟動(dòng)流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
springboot + mybatis + druid + 多數(shù)據(jù)源的問題詳解
這篇文章主要介紹了springboot + mybatis + druid + 多數(shù)據(jù)源的問題詳解,示例代碼文字相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09

