“J.U.C”:Phaser (r)

来源:互联网 发布:淘宝买iphone8靠谱吗 编辑:程序博客网 时间:2024/05/18 03:11

Phaser由java7中推出,是Java SE 7中新增的一个使用同步工具,在功能上面它与CyclicBarrier、CountDownLatch有些重叠,但是它提供了更加灵活、强大的用法。

CyclicBarrier,允许一组线程互相等待,直到到达某个公共屏障点。它提供的await()可以实现让所有参与者在临界点到来之前一直处于等待状态。

CountDownLatch,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。它提供了await()、countDown()两个方法来进行操作。

在Phaser中,它把多个线程协作执行的任务划分为多个阶段,编程时需要明确各个阶段的任务,每个阶段都可以有任意个参与者,线程都可以随时注册并参与到某个阶段。

构造

Phaser创建后,初始阶段编号为0,构造函数中指定初始参与个数。

注册:Registration

Phaser支持通过register()和bulkRegister(int parties)方法来动态调整注册任务的数量。

Arrival

每个Phaser实例都会维护一个phase number,初始值为0。每当所有注册的任务都到达Phaser时,phase number累加,并在超过Integer.MAX_VALUE后清零。arrive()和arriveAndDeregister()方法用于记录到达;其中arrive(),某个参与者完成任务后调用;arriveAndDeregister(),任务完成,取消自己的注册。arriveAndAwaitAdvance(),自己完成等待其他参与者完成,进入阻塞,直到Phaser成功进入下个阶段。

example 1

[java] view plain copy
 print?
  1. public class PhaserTest_1 {  
  2.     public static void main(String[] args) {  
  3.         Phaser phaser = new Phaser(5);  
  4.           
  5.         for(int i = 0 ; i < 5 ; i++){  
  6.             Task_01 task_01 = new Task_01(phaser);  
  7.             Thread thread = new Thread(task_01, "PhaseTest_" + i);  
  8.             thread.start();  
  9.         }  
  10.     }  
  11.       
  12.     static class Task_01 implements Runnable{  
  13.         private final Phaser phaser;  
  14.           
  15.         public Task_01(Phaser phaser){  
  16.             this.phaser = phaser;  
  17.         }  
  18.           
  19.         @Override  
  20.         public void run() {  
  21.             System.out.println(Thread.currentThread().getName() + "执行任务完成,等待其他任务执行......");  
  22.             //等待其他任务执行完成  
  23.             phaser.arriveAndAwaitAdvance();  //CyclicBarrier.await()
  24.             System.out.println(Thread.currentThread().getName() + "继续执行任务...");  
  25.         }  
  26.     }  
  27. }  

运行结果:

PhaseTest_0执行任务完成,等待其他任务执行......PhaseTest_1执行任务完成,等待其他任务执行......PhaseTest_3执行任务完成,等待其他任务执行......PhaseTest_2执行任务完成,等待其他任务执行......PhaseTest_4执行任务完成,等待其他任务执行......PhaseTest_4继续执行任务...PhaseTest_1继续执行任务...PhaseTest_0继续执行任务...PhaseTest_2继续执行任务...PhaseTest_3继续执行任务...

在该实例中我们可以确认,所有子线程的****+”继续执行任务…”,都是在线程调用arriveAndAwaitAdvance()方法之后执行的。

example 2

前面提到过,Phaser提供了比CountDownLatch、CyclicBarrier更加强大、灵活的功能,从某种程度上来说,Phaser可以替换他们:

[java] view plain copy
 print?
  1. public class PhaserTest_5 {  
  2.     public static void main(String[] args) {  
  3.         Phaser phaser = new Phaser(1);        //相当于CountDownLatch(1)   
  4.           
  5.         //五个子任务  
  6.         for(int i = 0 ; i < 3 ; i++){  
  7.             Task_05 task = new Task_05(phaser);  
  8.             Thread thread = new Thread(task,"PhaseTest_" + i);  
  9.             thread.start();  
  10.         }  
  11.           
  12.         try {  
  13.             //等待3秒  
  14.             Thread.sleep(3000);  
  15.         } catch (InterruptedException e) {  
  16.             e.printStackTrace();  
  17.         }  
  18.         phaser.arrive();        //countDownLatch.countDown()  
  19.     }  
  20.       
  21.     static class Task_05 implements Runnable{  
  22.         private final Phaser phaser;  
  23.           
  24.         Task_05(Phaser phaser){  
  25.             this.phaser = phaser;  
  26.         }  
  27.           
  28.         @Override  
  29.         public void run() {  
  30.             phaser.awaitAdvance(phaser.getPhase());        //countDownLatch.await()  
  31.             System.out.println(Thread.currentThread().getName() + "执行任务...");  
  32.         }  
  33.     }  
  34. }  

在这里,任务一开始并没有真正执行,而是等待三秒后执行。

对于CyclicBarrier就更加简单了,直接arriveAndAwaitAdvance()方法替换,如example 1。

example 3

在CyclicBarrier中当任务执行完之后可以执行一个action,在Phaser中同样有一个对应的action,只不过Phaser需要重写onAdvance()方法:

[java] view plain copy
 print?
  1. public class PhaserTest_3 {  
  2.     public static void main(String[] args) {  
  3.              Phaser phaser = new Phaser(3){  
  4.            /** 
  5.              * registeredParties:线程注册的数量 
  6.              * phase:进入该方法的线程数, 
  7.              */  
  8.              protected boolean onAdvance(int phase, int registeredParties) {   
  9.                  System.out.println("执行onAdvance方法.....;phase:" + phase + "registeredParties=" + registeredParties);  
  10.                  return phase == 3;   
  11.              }  
  12.         };  
  13.           
  14.         for(int i = 0 ; i < 3 ; i++){  
  15.             Task_03 task = new Task_03(phaser);  
  16.             Thread thread = new Thread(task,"task_" + i);  
  17.             thread.start();  
  18.         }  
  19.         while(!phaser.isTerminated()){  
  20.             phaser.arriveAndAwaitAdvance();    //主线程一直等待  
  21.         }  
  22.         System.out.println("主线程任务已经结束....");  
  23.     }  
  24.       
  25.     static class Task_03 implements Runnable{  
  26.         private final Phaser phaser;  
  27.           
  28.         public Task_03(Phaser phaser){  
  29.             this.phaser = phaser;  
  30.         }  
  31.           
  32.         @Override  
  33.         public void run() {  
  34.             do{  
  35.                 try {  
  36.                     Thread.sleep(500);  
  37.                 } catch (InterruptedException e) {  
  38.                     e.printStackTrace();  
  39.                 }  
  40.                 System.out.println(Thread.currentThread().getName() + "开始执行任务...");  
  41.                 phaser.arriveAndAwaitAdvance();  //CyclicBarrier.await()
  42.             }while(!phaser.isTerminated());  
  43.         }  
  44.     }  
  45. }  

运行结果:

task_0开始执行任务...task_1开始执行任务...task_1执行onAdvance方法.....;phase:0registeredParties=3task_2开始执行任务...task_0开始执行任务...task_1开始执行任务...task_0执行onAdvance方法.....;phase:1registeredParties=3task_2开始执行任务...task_2执行onAdvance方法.....;phase:2registeredParties=3主线程任务已经结束....task_0开始执行任务...

 

参考博文:

1、What’s New on Java 7 Phaser

2、http://blog.csdn.net/andycpp/article/details/8838820

0 0