CountDownLatch, CyclicBarrier, Semaphore 和 Phaser
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 }
执行结果


浙公网安备 33010602011771号