JUC之辅助类
CountDownLatch(閉鎖)
什么是CountDownLatch
CountDownLatch是一個同步工具類, 用來協調多個線程之間的同步, 或者說起到線程之間的通信(而不是用作互斥的作用)。
CountDownLatch能夠使一個線程在等待另外一些線程完成各自工作之后, 再繼續執行。使用一個計數器進行實現。計數器初始值為線程的數量。當每一個線程完成自己任務后, 計數器的值就會減一, 當計數器的值為0時, 表示所有的線程都已經完成一些任務, 然后在CountDownLatch上等待的線程就可以恢復執行接下來的任務。
CountDownLatch的用法
- 當一個或多個線程調用await方法時, 這些線程會阻塞
- 其它線程調用countDown方法會將計數器減1(調用countDown方法的線程不會阻塞)
- 計數器的值變為0時, 因await方法阻塞的線程會被喚醒, 繼續執行
案例: 秦始皇滅掉六國, 一統天下
//使用枚舉類創建六個國家 enum CountryEnum {one(1, "齊"), two(2, "楚"), three(3, "燕"),four(4, "趙"), five(5, "魏"), six(6, "韓");private Integer retCode;private String retMessage;private CountryEnum(Integer retCode, String retMessage) {this.retCode = retCode;this.retMessage = retMessage;}public static CountryEnum getCountryEnum(Integer index) {CountryEnum[] countryEnums = CountryEnum.values();for (CountryEnum countryEnum : countryEnums) {if (countryEnum.getRetCode().equals(index)) {return countryEnum;}}return null;}public Integer getRetCode() {return retCode;}public String getRetMessage() {return retMessage;} } public class CountDownLatchDemo {public static void main(String[] args) throws Exception {CountDownLatch countDownLatch = new CountDownLatch(6);for (int i = 1; i <= 6; i++) {new Thread(() -> {System.out.println(Thread.currentThread().getName() + "國, 被滅");countDownLatch.countDown();}, CountryEnum.getCountryEnum(i).getRetMessage()).start();}countDownLatch.await();System.out.println(Thread.currentThread().getName() + "\t" + "秦國一統天下");} }運行結果:
額, 好像沒有按照歷史順序來, 不過無傷大雅
CountDownLatch的不足
CountDownLatch是一次性的, 計數器的值只能在構造方法中初始化一次, 之后沒有任何機制再次對其設置值, 當CountDownLatch使用完畢后, 它不能再次被使用。
CyclicBarrier(循環柵欄)
CyclicBarrier是什么
CyclicBarrier是一個同步輔助類, 它允許一組線程相互等待直到所有線程都到達一個公共的屏障點。
在程序中有固定數量的線程, 這些線程有時候必須等待彼此, 意思就是每個線程都得執行到等待點進行等待, 直到所有線程都執行到等待點, 才會繼續往下執行。這種情況下, 使用CyclicBarrier很有幫助。這個屏障之所以用循環修飾, 是因為在所有的線程釋放彼此之后, 這個屏障是可以重新使用的。
CyclicBarrier的用法
構造方法:
-
CyclicBarrier(int parties), 當等待線程數量達到parties時, 放行所有線程
-
CyclicBarrier(int parties,Runnable barrierAction), 當等待線程數量達到parties時, 放行所有線程, 并由最后一個線程執行barrierAction
案例: 收集七龍珠召喚神龍
public class CyclicBarrierDemo {//創建固定值private static final int NUMBER = 7;public static void main(String[] args) {//創建CyclicBarrierCyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {System.out.println("召喚神龍");});for (int i = 1; i <= 7; i++) {new Thread(() -> {System.out.println(Thread.currentThread().getName() + "星龍珠");//等待try {cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}}, "" + i).start();}} }運行結果:
CyclicBarrier與CountDownLatch的區別
- CyclicBarrier是對計數器做加法
- CountDownLatch是對計數器做減法
- CountdownLatch是一次性的
- CycliBarrier是可以重復使用的, 使用reset()方法即可重置計數器
Semaphore(信號燈)
Semaphore是什么
Semaphore是計數信號量。Semaphore管理一系列許可。每個acquire方法阻塞, 直到有一個許可證可以獲得然后拿走一個許可證;每個release方法增加一個許可, 這可能會釋放一個阻塞的acquire方法。然而, 其實并沒有實際的許可這個對象, Semaphore只是維持了一個可獲得許可證的數量。
Semaphore的用法
- acquire(獲取)當一個線程調用acquire操作時, 它要么通過成功獲取信號量(信號量減1), 要么一直等下去, 直到有線程釋放信號量, 或超時。
- release(釋放)實際上會將信號量的值加1, 然后喚醒等待的線程。
- 信號量主要用于兩個目的, 一個是用于多個共享資源的互斥使用, 另一個用于并發線程數的控制。
案例: 停車場搶車位
public class SemaphoreDemo {public static void main(String[] args) {//創建Semaphore, 設置許可量, 模擬三個車位Semaphore semaphore = new Semaphore(3);//模擬六輛汽車for (int i = 1; i <= 6; i++) {new Thread(()->{try {//獲取許可semaphore.acquire();System.out.println(Thread.currentThread().getName() + "號車搶到車位");//設置隨機停車時間TimeUnit.SECONDS.sleep(new Random().nextInt(5));System.out.println(Thread.currentThread().getName() + "號車離開車位");} catch (InterruptedException e) {e.printStackTrace();} finally {//釋放許可semaphore.release();}}, "" + i).start();}} }運行結果:
可以看到, 如果有三個線程得到了許可, 那么剩下的線程就會被阻塞, 知道有線程釋放許可, 才會隨機釋放一個被阻塞的線程獲得許可。
我的個人主頁: www.ayu.link
本文連接: ┏ (゜ω゜)=?
總結
- 上一篇: java graphics 模糊_使用G
- 下一篇: 学金融离不开计算机,如何看待学计算机的被