CountDownLatch, CyclicBarrier, Semaphore 和 Phaser
阿新 • • 發佈:2020-09-07
CountDownLatch
計數與阻塞是分離的(相對靈活),當計數器為0時釋放阻塞執行緒,不可重置,不可複用。
參與計數的執行緒不用阻塞,需要阻塞的執行緒不用參與計數。
主要方法
await:阻塞當前執行緒(可設定超時時間)
countdown:計數減1
getCount:返回當前計數
示例
1 public class CountDownLatchTest { 2 3 static final CountDownLatch countDownLatch = new CountDownLatch(5); 4 5 public static void main(String[] args) {6 for (int i = 0; i < 5; i++) { 7 new Thread(()->{ 8 try { 9 Thread.sleep(new Double(Math.random() * 5000).longValue()); 10 System.out.println(Thread.currentThread().getName() + "計數"); 11 countDownLatch.countDown(); //計數減1 12 System.out.println(Thread.currentThread().getName() + "繼續執行"); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 }).start(); 17 } 18 try { 19 System.out.println("主執行緒進入阻塞");20 countDownLatch.await(); // 阻塞,計數器為0時釋放 21 System.out.println("主執行緒開始執行"); 22 } catch (InterruptedException e) { 23 e.printStackTrace(); 24 } 25 } 26 }
執行結果
Cyclic Barrier
計數與阻塞是不分離的(不夠靈活),當計數器達到指定值時釋放,可重置,可複用。
參與計數的一定是阻塞執行緒,需要阻塞的執行緒一定參與計數。
主要方法
過載的構造方法:CyClicBarrier(int parties, Runnable barrierAction)(指定屏障操作)
await:阻塞當前執行緒,並且計數加1(可設定超時時間)
getNumberWaiting:返回當前阻塞的執行緒數目(當前計數)
getParties:返回計數器指定的值
reset:將迴圈屏障重置為初始狀態(計數歸0)
示例
1 public class CyclicBarrierTest { 2 3 static final CyclicBarrier cyclicBarrier = new CyclicBarrier(5); 4 5 public static void main(String[] args) { 6 for (int i = 0; i < 5; i++) { 7 new Thread(()->{ 8 try { 9 Thread.sleep(new Double(Math.random() * 5000).longValue()); 10 System.out.println(Thread.currentThread().getName() + "阻塞並且計數"); 11 cyclicBarrier.await(); // 阻塞並且計數加1 12 System.out.println(Thread.currentThread().getName() + "繼續執行第一部分"); 13 Thread.sleep(new Double(Math.random() * 5000).longValue()); 14 System.out.println(Thread.currentThread().getName() + "阻塞並且計數"); 15 cyclicBarrier.await(); // 阻塞並且計數加1 16 System.out.println(Thread.currentThread().getName() + "繼續執行第二部分"); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } catch (BrokenBarrierException e) { 20 e.printStackTrace(); 21 } 22 }).start(); 23 } 24 } 25 }
執行結果
Semaphore
類似鎖機制,但本質依然是執行緒的排程,可以控制同時使用該訊號量的執行緒個數。
主要方法
過載的構造方法:Semaphore(int permits, boolean fair)(指定公平性)
acquire:從此訊號量獲取一個許可,獲取到許可之前執行緒將被阻塞
release:釋放當前許可
availablePermits:返回此訊號量的可用許可數目
示例
1 public class SemaphoreTest { 2 3 static final Semaphore semaphore = new Semaphore(2); 4 5 public static void main(String[] args) { 6 for (int i = 0; i < 5; i++) { 7 new Thread(()->{ 8 try { 9 semaphore.acquire(); // 獲取一個許可 10 System.out.println(Thread.currentThread().getName() + "開始執行"); 11 Thread.sleep(new Double(Math.random() * 5000).longValue()); 12 System.out.println(Thread.currentThread().getName() + "執行結束"); 13 semaphore.release(); // 釋放當前許可 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 }).start(); 18 } 19 } 20 }
執行結果
Phaser
結合了CountDown和CyclicBarrier的特性,還具備分階段的功能。
主要方法
arrive:抵達
awaitAdvance:阻塞等待某階段結束
arriveAndAwaitAdvance:抵達並且阻塞等待
register:註冊
arriveAndDeregister:抵達並且登出
getPhase:獲得當前階段數
示例
1 public class PhaserTest { 2 3 static final Phaser phaser = new Phaser(2); 4 5 public static void main(String[] args) { 6 for (int i = 0; i < 3; i++) { 7 new Thread(()->{ 8 try { 9 Thread.sleep(new Double(Math.random() * 5000).longValue()); 10 if (phaser.getPhase() == 0) { 11 System.out.println(Thread.currentThread().getName() + "抵達第一階段"); 12 phaser.arriveAndAwaitAdvance(); 13 } 14 Thread.sleep(new Double(Math.random() * 5000).longValue()); 15 if (phaser.getPhase() <= 1) { 16 System.out.println(Thread.currentThread().getName() + "抵達第二階段"); 17 phaser.arriveAndAwaitAdvance(); 18 } 19 Thread.sleep(new Double(Math.random() * 5000).longValue()); 20 if (phaser.getPhase() <= 2) { 21 System.out.println(Thread.currentThread().getName() + "抵達第三階段"); 22 phaser.arrive(); 23 } 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 }).start(); 28 } 29 phaser.awaitAdvance(0); 30 System.out.println("第一階段結束"); 31 phaser.register(); // 註冊一個 32 phaser.awaitAdvance(1); 33 System.out.println("第二階段結束"); 34 phaser.arriveAndDeregister(); // 登出一個 35 phaser.awaitAdvance(2); 36 System.out.println("第三階段結束"); 37 } 38 }