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