網(wǎng)站首頁 編程語言 正文
Semaphore,CountdownLatch,CyclicBarrier都是java提供的同步輔助類。
上一篇對(duì)Semaphore有了一定的了解,本篇?jiǎng)t針對(duì)CountdownLatch以及CyclicBarrier進(jìn)行一定的總結(jié)。
一、CountdownLatch
1)CountdownLatch是什么?
CyclicBarrier的字面意思是可循環(huán)使用(Cyclic)的屏障(Barrier)
能夠使一個(gè)線程等待其他線程完成各自的工作之后再執(zhí)行。例如zookeeper分布式鎖的實(shí)現(xiàn)。而Semaphore則主要強(qiáng)調(diào)的是資源有限。
2)CountdownLatch使用場(chǎng)景
比如老公陪同媳婦去醫(yī)院,媳婦等候醫(yī)生看病,老公則針對(duì)單子去拿藥,兩者都完工,則一起回家。再比如老板等10個(gè)員工開會(huì),只有10個(gè)員工都到齊了,會(huì)議才能開始等等場(chǎng)景。
3)應(yīng)用demo
舉例說明老板等待員工開會(huì)的場(chǎng)景:
public static void main(String[] args) {
//老板需要等待15個(gè)員工會(huì)議室開會(huì)
final CountDownLatch latch = new CountDownLatch(15);
for (int i = 0; i < 15; i++) {
Random random = new Random();
final int timer = random.nextInt(1000);
new Thread(() -> {
try {
System.out.println("子線程" + Thread.currentThread().getName() + "正在趕路");
//模仿每個(gè)員工走自己線程需要的時(shí)間
Thread.sleep(1000 + timer);
//調(diào)用latch的countDown方法使計(jì)數(shù)器-1;一共15個(gè)
latch.countDown();
System.out.println("子線程" + Thread.currentThread().getName() + "到會(huì)議室了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
try {
System.out.println("領(lǐng)導(dǎo)等待員工會(huì)議室開會(huì)...");
//主線程阻塞等待計(jì)數(shù)器歸零
latch.await();
System.out.println("員工都來了,會(huì)議開始");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
執(zhí)行結(jié)果:
子線程Thread-1正在趕路
子線程Thread-3正在趕路
子線程Thread-0正在趕路
子線程Thread-2正在趕路
子線程Thread-4正在趕路
子線程Thread-5正在趕路
子線程Thread-6正在趕路
子線程Thread-7正在趕路
子線程Thread-8正在趕路
子線程Thread-9正在趕路
子線程Thread-10正在趕路
子線程Thread-11正在趕路
子線程Thread-12正在趕路
子線程Thread-13正在趕路
領(lǐng)導(dǎo)等待員工會(huì)議室開會(huì)…
子線程Thread-14正在趕路
子線程Thread-5到會(huì)議室了
子線程Thread-1到會(huì)議室了
子線程Thread-12到會(huì)議室了
子線程Thread-13到會(huì)議室了
子線程Thread-4到會(huì)議室了
子線程Thread-6到會(huì)議室了
子線程Thread-2到會(huì)議室了
子線程Thread-0到會(huì)議室了
子線程Thread-3到會(huì)議室了
子線程Thread-10到會(huì)議室了
子線程Thread-14到會(huì)議室了
子線程Thread-8到會(huì)議室了
子線程Thread-9到會(huì)議室了
子線程Thread-7到會(huì)議室了
子線程Thread-11到會(huì)議室了
員工都來了,會(huì)議開始
4)源碼分析
核心關(guān)注方法只有兩個(gè),latch.countDown();和latch.await();
countDown() 方法每次調(diào)用都會(huì)將 state 減 1,直到state 的值為 0;而 await 是一個(gè)阻塞方法,當(dāng) state 減 為 0 的時(shí)候,await 方法才會(huì)返回。await 可以被多個(gè)線程調(diào)用,大家在這個(gè)時(shí)候腦子里要有個(gè)圖:所有調(diào)用了await 方法的線程阻塞在 AQS 的阻塞隊(duì)列中,等待條件滿(state == 0),將線程從隊(duì)列中一個(gè)個(gè)喚醒過來。
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
在 CountDownLatch 內(nèi)部寫了一個(gè) Sync 并且繼承了 AQS 這個(gè)抽象類重寫了 AQS中的共享鎖方法。這段代碼主要是判定當(dāng)前線程是否獲取到了共享鎖
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//state 如果不等于 0,說明當(dāng)前線程需要加入到共享鎖隊(duì)列中
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
//在共享可中斷模式下獲取。
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
//創(chuàng)建一個(gè)共享模式的節(jié)點(diǎn)添加到隊(duì)列中
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
//嘗試獲取鎖
int r = tryAcquireShared(arg);
//r>=0 表示獲取到了執(zhí)行權(quán)限,這個(gè)時(shí)候因?yàn)?state!=0,所以不會(huì)執(zhí)行這段代碼
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
//阻塞線程
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
二、CyclicBarrier
1)CyclicBarrier是什么?
柵欄屏障,讓一組線程到達(dá)一個(gè)屏障(也可以叫同步點(diǎn))時(shí)被阻塞,直到最后一個(gè)線程到達(dá)屏障時(shí),屏障才會(huì)開門,所有被屏障攔截的線程才會(huì)繼續(xù)運(yùn)行。
簡(jiǎn)單理解就是:多個(gè)線程之間互相等待,滿足條件在同一時(shí)間進(jìn)行。
2)CyclicBarrier使用場(chǎng)景
可以用于多線程計(jì)算數(shù)據(jù),最后合并計(jì)算結(jié)果的場(chǎng)景。
又比如旅行團(tuán)旅行,需要大家都到齊,證件都辦理好,才能出發(fā)。
3)應(yīng)用demo
旅行團(tuán)旅行,需要大家都到齊,證件都辦理好,上旅行車才能出發(fā)。
public class CyclicBarrierTest1 extends Thread{
private final CyclicBarrier barrier;
//隨機(jī)值處理
private final Random random = new Random();
public CyclicBarrierTest1(String name,CyclicBarrier barrier) {
super(name);
this.barrier = barrier;
}
/**
* 重寫run方法
*/
@Override
public void run() {
try {
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getName() + " - 已經(jīng)到達(dá)旅行團(tuán)");
barrier.await();
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getName() + " - 證件已經(jīng)辦理好");
barrier.await();
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getName() + " - 已經(jīng)上旅行車");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
super.run();
}
public static void main(String[] args) {
//旅行團(tuán)5個(gè)游客
CyclicBarrier cyclicBarrier=new CyclicBarrier(5);
for (int i=0;i<5;i++){
new CyclicBarrierTest1("游客-" + (i + 1), cyclicBarrier).start();
}
}
}
游客-5 - 已經(jīng)到達(dá)旅行團(tuán)
游客-3 - 已經(jīng)到達(dá)旅行團(tuán)
游客-2 - 已經(jīng)到達(dá)旅行團(tuán)
游客-1 - 已經(jīng)到達(dá)旅行團(tuán)
游客-4 - 已經(jīng)到達(dá)旅行團(tuán)
游客-2 - 證件已經(jīng)辦理好
游客-4 - 證件已經(jīng)辦理好
游客-1 - 證件已經(jīng)辦理好
游客-3 - 證件已經(jīng)辦理好
游客-5 - 證件已經(jīng)辦理好
游客-1 - 已經(jīng)上旅行車
游客-2 - 已經(jīng)上旅行車
游客-3 - 已經(jīng)上旅行車
游客-5 - 已經(jīng)上旅行車
游客-4 - 已經(jīng)上旅行車
原文鏈接:https://blog.csdn.net/huo065000/article/details/120649318
相關(guān)推薦
- 2022-12-07 C語言內(nèi)存分布與heap空間分別詳細(xì)講解_C 語言
- 2022-02-13 pip install dlib報(bào)C++11 is required to use dlib
- 2023-04-06 C#?Csv實(shí)現(xiàn)基本的讀寫和轉(zhuǎn)換DataTable_C#教程
- 2022-05-18 Jenkins使用publish?html?report插件展示HTML報(bào)告的方法_相關(guān)技巧
- 2022-09-04 python接口自動(dòng)化之正則用例參數(shù)化的示例詳解_python
- 2021-12-13 C語言魔方陣的三種實(shí)現(xiàn)方法_C 語言
- 2021-12-11 C語言SetConsoleCursorPosition函數(shù)使用方法_C 語言
- 2022-07-21 toggleRowSelection失效的2個(gè)原因
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支