CountDownLatch、CyclicBarrier、Semaphore 三者之間的區別和使用


CountDownLatch類計數器的使用

主要有兩個方法,當一個或者多個線程調用await()方法時,調用的線程會被阻塞,其它線程調用countDown()方法時將計數器減去1(調用countDown()方法的線程不會被阻塞),但計數器的值變為0時,因為調用await()方法被阻塞的線程會被喚醒,繼續執行。

代碼舉例:

 1 package com.countdownlatch;
 2 
 3 import java.util.concurrent.CountDownLatch;
 4 
 5 /**
 6  * CountDownLatch  類計數器的使用
 7  * CountDownLatch  主要有兩個方法,當一個或者多個線程調用await()方法時,調用線程會被阻塞,
 8  * 其它線程調用countDown()方法將計數器減 1 (調用countdown()方法的線程不會被阻塞),
 9  * 但計數器的值變為零時,因調用await()方法被阻塞的線程會被喚醒,繼續執行。
10  */
11 public class CountDownLatchDemo {
12     public static void main(String[] args) throws InterruptedException {
13         CountDownLatch count = new CountDownLatch(6);
14         for (int i = 1; i <= 6; i++) {
15             new Thread(() -> {
16                 System.out.println(Thread.currentThread().getName() + "\t 國,被滅");
17                 count.countDown();//逐個減一,只有所有的線程執行完成,才會執行下面的代碼(倒計數 )
18             }, CountDownLatchEnum.getMessenger(i).getRetMessenger()).start();
19         }
20         count.await();//判斷上面的線程是否執行完成,若未完成;則返回上面繼續執行,直到上面的線程執行完成,才會執行下面的代碼
21         System.out.println(Thread.currentThread().getName().replaceAll("main","秦") + "\t 國,統一六國");
22     }
23 }
View Code

枚舉輔助類:

 1 package com.countdownlatch;
 2 
 3 
 4 /**
 5  * CountDownLatch 的枚舉輔助類
 6  */
 7 public enum CountDownLatchEnum {
 8     ONE(1, "齊"), TWO(2, "楚"), THREE(3, "燕"), FORE(4, "韓"), FINE(5, "趙"), SIT(6, "魏");
 9     private int retCode;
10     private String retMessenger;
11 
12     public int getRetCode() {
13         return retCode;
14     }
15 
16     public String getRetMessenger() {
17         return retMessenger;
18     }
19 
20     CountDownLatchEnum(int retCode, String retMessenger) {
21         this.retCode = retCode;
22         this.retMessenger = retMessenger;
23     }
24 
25     public static CountDownLatchEnum getMessenger(int index) {
26         CountDownLatchEnum[] elemts = CountDownLatchEnum.values();
27         for (CountDownLatchEnum iter : elemts) {
28             if (iter.getRetCode() == index) {
29                 return iter;
30             }
31         }
32         return null;
33     }
34 }
View Code

CyclicBarrier類型的用法正好和CountDownLatch意思相反

等所有線程都收集完成,才會執行下一個方法;比如:7個人會議,只有7個人全部到齊了才可以開會,否則只能等着。

代碼舉例:

 1 package com.countdownlatch;
 2 
 3 import java.util.concurrent.BrokenBarrierException;
 4 import java.util.concurrent.CyclicBarrier;
 5 
 6 /**
 7  * CyclicBarrier  等所有的線程都收集完成,才會執行下一個方法;比如:7個人會議;只有7個人
 8  * 全部到齊了才可以開會;否則只能等着。
 9  */
10 public class CyclicBarrierDemo {
11     public static void main(String[] args) {
12         CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
13             System.out.println("人員到齊,會議開始....");
14         });
15         for (int i = 1; i <= 7; i++) {
16             new Thread(() -> {
17                 System.out.println(Thread.currentThread().getName() + "\t 簽到...");
18                 try {
19                     cyclicBarrier.await();
20                 } catch (InterruptedException e) {
21                     e.printStackTrace();
22                 } catch (BrokenBarrierException e) {
23                     e.printStackTrace();
24                 }
25             }, CyclicBarrierEnum.getMessenger(i).getRetMessenger()).start();
26         }
27     }
28 }
View Code

枚舉輔助類:

 1 package com.countdownlatch;
 2 
 3 
 4 /**
 5  * CyclicBarrier 的枚舉輔助類
 6  */
 7 public enum CyclicBarrierEnum {
 8     ONE(1, "班長"), TWO(2, "副班長"), THREE(3, "學習委員"), FORE(4, "紀律委員"), FINE(5, "生活委員"), SIT(6, "勞動委員"), SERVE(7, "團支書");
 9     private int retCode;
10     private String retMessenger;
11 
12     public int getRetCode() {
13         return retCode;
14     }
15 
16     public String getRetMessenger() {
17         return retMessenger;
18     }
19 
20     CyclicBarrierEnum(int retCode, String retMessenger) {
21         this.retCode = retCode;
22         this.retMessenger = retMessenger;
23     }
24 
25     public static CyclicBarrierEnum getMessenger(int index) {
26         CyclicBarrierEnum[] elemts = CyclicBarrierEnum.values();
27         for (CyclicBarrierEnum iter : elemts) {
28             if (iter.getRetCode() == index) {
29                 return iter;
30             }
31         }
32         return null;
33     }
34 }
View Code

SemapJore 信號量(燈)

主要有兩個目的:1、多個共享資源的互斥使用

2、用於並發線程數的控制

代碼舉例:

 1 package com.countdownlatch;
 2 
 3 import java.util.concurrent.Semaphore;
 4 import java.util.concurrent.TimeUnit;
 5 
 6 /**
 7  * Semaphore 信號量(燈)主要用於兩個目的:一是多個共享資源的互斥使用,另一個用於並發線程數的控制
 8  * <p>
 9  * 比如:爭車位,開走一輛,進入一輛,沒位置的只能等着,只要有其它車輛開走,立馬搶空車位。
10  */
11 public class SemaphoreDemo {
12     public static void main(String[] args) {
13         //模擬 3 個停車位
14         Semaphore semaphore = new Semaphore(3);
15         for (int i = 1; i <= 6; i++) {//6輛車去搶三個車位
16             new Thread(() -> {
17                 try {
18                     semaphore.acquire();//搶到車位,停車場的空位減 1
19                     System.out.println(Thread.currentThread().getName() + "\t 搶到車位");
20                     try {
21                         TimeUnit.SECONDS.sleep(3);
22                     } catch (InterruptedException e) {
23                         e.printStackTrace();
24                     }//停3 秒后離開停車場
25                     System.out.println(Thread.currentThread().getName() + "\t 停車3秒后,離開停車場");
26                 } catch (InterruptedException e) {
27                     e.printStackTrace();
28                 } finally {
29                     semaphore.release();//離開停車場,釋放停車場的位置;讓其它車輛爭搶位置
30                 }
31             }, String.valueOf(i)).start();
32         }
33 
34     }
35 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM