【Java核心-进阶】Semaphore、CountDownLatch、CyclicBarrier、Phaser

Java并发包中有很多可以实现同步的结构。以下几种就属于典型的“非显式”锁:

  • Semaphore:Java版本的信号量实现。

  • CountDownLatch:允许一个或多个线程等待某些操作完成。

  • CyclicBarrier:允许多个线程等待达到某个屏障。

  • Phaser:分阶段地等待多个线程达到某个屏障。

CountDownLatch vs CyclicBarrier

CountDownLatch 和 CyclicBarrier 都可用于等待多个线程完成相关操作(达到某个同步点)。

CountDownLatch 侧重于 让一个线程等待其它多个线程执行完成任务。

CyclicBarrier 侧重于 多个线程线程相互等待至某个状态,然后它们再开始同时执行。

最主要区别:

  • CountDownLatch 不可以被重置,所以无法重用;

  • CyclicBarrier 可以被重置,所以可以重用。

    正常情况下会被自动重置。如果主动调用 reset() 时,有线程还在等待,等待线程会抛异常 BrokenBarrierException。

 

CountDownLatch vs Phaser

Phaser 和 CountDownLatch、CyclicBarrier 都有很相似的地方。

Phaser 顾名思义,就是可以分阶段的进行线程同步。

  • CountDownLatch 只能在创建实例时,通过构造方法指定同步数量;

  • Phaser 支持线程动态地向它注册。

    利用这个动态注册的特性,可以达到分阶段同步控制的目的:

    注册一批操作,等待它们执行结束;再注册一批操作,等它们结束...

 

Semaphore

Semaphore,信号量,就是计数器。它可以限制对资源的访问,防止过多使用者同时占用。

 

两个主要方法:acquire()、release(int permits)

典型使用模式:

Java代码

 

  1. public static void main(String[] args) {  

  2.   Semaphore semaphore = new Semaphore(5);  

  3.   for (int i=0; i<10; i++) {  

  4.     Thread t = new Thread(new Worker(semaphore));  

  5.     t.start();  

  6.   }  

  7. }  

  8.   

  9. static class Worker implements Runnable {  

  10.   private Semaphore semaphore;  

  11.   Worker(Semaphore semaphore) {  

  12.     this.semaphore = semaphore;  

  13.   }  

  14.   

  15.   @Override  

  16.   public void run() {  

  17.     try {  

  18.       semaphore.acquire();  

  19.     } catch (InterruptedException e) {  

  20.       e.printStackTrace();  

  21.     } finally {  

  22.       semaphore.release();  

  23.     }  

  24.   }  

  25. }  

CountDownLatch

两个主要方法:await()、countDown()

典型使用模式:

Java代码

 

  1. public static void main(String[] args) {  

  2.   CountDownLatch latch = new CountDownLatch(5);  

  3.   for (int i=0; i<5; i++) {  

  4.     Thread t = new Thread(new Worker(latch));  

  5.     t.start();  

  6.   }  

  7.   

  8.   latch.await();  

  9. }  

  10.   

  11. static class Worker implements Runnable {  

  12.   private CountDownLatch latch;  

  13.   

  14.   Worker(CountDownLatch latch) {  

  15.     this.latch = latch;  

  16.   }  

  17.   

  18.   @Override  

  19.   public void run() {  

  20.     lathc.countDown();  

  21.   }  

  22. }  

 

CyclicBarrier

主要方法:await()。正常情况下,CyclicBarrier 是被自动重置。

典型使用模式:

Java代码

 

  1. public static void main(String[] args) {  

  2.   CyclicBarrier barrier = new CyclicBarrier(5,  

  3.       () -> System.out.println("Action go again."));  

  4.   

  5.   for (int i=0; i<5; i++) {  

  6.     String workerName = "Worker-" + i;  

  7.     Thread t = new Thread(new Worker(workerName, barrier));  

  8.     t.start();  

  9.   }  

  10. }  

  11.   

  12. static class Worker implements Runnable {  

  13.   private String name;  

  14.   private CyclicBarrier barrier;  

  15.   

  16.   Worker(String name, CyclicBarrier barrier) {  

  17.     this.name = name;  

  18.     this.barrier = barrier;  

  19.   }  

  20.   

  21.   @Override  

  22.   public void run() {  

  23.     try {  

  24.       for (int i=0; i<3; i++) {  

  25.         System.out.println(name + " executed " + i);  

  26.         barrier.await();  

  27.       }  

  28.     } catch (BrokenBarrierException | InterruptedException e) {  

  29.       e.printStackTrace();  

  30.     }  

  31.   }  

  32. }  

 

Phaser

典型使用模式:

Java代码

 

  1. public static void main(String[] args) {  

  2.   // 初始 party 数为1,是为了通过主线程控制 phaser 不同阶段的操作  

  3.   Phaser phaser = new Phaser(1);  

  4.   

  5.   // 第一阶段,5个Worker  

  6.   for (int i = 0; i < 5; i++) {  

  7.     String workerName = "Phase-1-Worker-" + i;  

  8.     Thread t = new Thread(new Worker(workerName, phaser));  

  9.     t.start();  

  10.   }  

  11.   // 开始执行第一阶段:主线程也到达第一阶段  

  12.   phaser.arriveAndAwaitAdvance();  

  13.   

  14.   // 第二阶段,3个Worker  

  15.   for (int i = 0; i < 3; i++) {  

  16.     String workerName = "Phase-2-Worker-" + i;  

  17.     Thread t = new Thread(new Worker(workerName, phaser));  

  18.     t.start();  

  19.   }  

  20.   // 开始执行第二阶段:主线程也到达第二阶段  

  21.   phaser.arriveAndAwaitAdvance();  

  22.   

  23.   // 各阶段都结束:(主线程)从 phaser 撤销  

  24.   phaser.arriveAndDeregister();  

  25. }  

  26.   

  27. static class Worker implements Runnable {  

  28.   private String name;  

  29.   private Phaser phaser;  

  30.   

  31.   Worker(String name, Phaser phaser) {  

  32.     this.name = name;  

  33.     this.phaser = phaser;  

  34.   

  35.     // 将当前线程注册到 phaser  

  36.     phaser.register();  

  37.   }  

  38.   

  39.   @Override  

  40.   public void run() {  

  41.     // 到达 phaser,并等待其它线程也到达  

  42.     phaser.arriveAndAwaitAdvance();  

  43.   

  44.     System.out.println(name + " done.");  

  45.   

  46.     // 到达 phaser,并将 Worker 从 phaser 撤销  

  47.     phaser.arriveAndDeregister();  

  48.   }  

  49. }  

 

你可能感兴趣的:(Java)