天天看点

Java并发编程-同步辅助类之Phaser

在前面已经学习过

Java并发编程-同步辅助类之CountDownLatch

Java并发编程-同步辅助类之CyclicBarrier

这篇文章介绍另一个辅助类Phaser,它是Jdk 1.7才添加的新的功能,它可以实现和CountDownLatch/CyclicBarrier类似的功能,但Phaser的功能更多,更加的灵活,它支持任务在多个点都进行同步,支持动态调整注册任务的数量。当然你也可以使用CountDownLatch,但你必须创建多个CountDownLatch对象,每一阶段都需要一个CountDownLatch对象。

操作方法

  • Phaser(int parties),构造方法,与CountDownLatch一样,传入同步的线程数,也支持层次构造Phaser(Phaser parent)。
  • register(),bulkRegister(int Parties),动态添加一个或多个参与者。
  • arriveAndDeregister()方法,动态撤销线程在phaser的注册,通知phaser对象,该线程已经结束该阶段且不参与后面阶段。
  • isTerminated(),当phaser没有参与同步的线程时(或者onAdvance返回true),phaser是终止态(如果phaser进入终止态arriveAndAwaitAdvance()和awaitAdvance()都会立即返回,不在等待)isTerminated返回true。
  • arrive()方法,通知phaser该线程已经完成该阶段,但不等待其他线程。
  • arriveAndAwaitAdvance()方法,类似await()方法,记录到达线程数,阻塞等待其他线程到达同步点后再继续执行。
  • awaitAdvance(int phase) /awaitAdvanceInterruptibly(int phase) ,传入阶段数,只有当前阶段等于phase阶段时才阻塞等待。后者如果线程在休眠被中断会抛出InterruptedException异常(phaser的其他方法对中断都不会抛出异常)。
  • onAdvance(int phase, int registeredParties)方法。参数phase是阶段数,每经过一个阶段该数加1,registeredParties是当前参与的线程数。此方法有2个作用:1、当每一个阶段执行完毕,此方法会被自动调用,因此,重载此方法写入的代码会在每个阶段执行完毕时执行,相当于CyclicBarrier的barrierAction。2、当此方法返回true时,意味着Phaser被终止,因此可以巧妙的设置此方法的返回值来终止所有线程。例如:若此方法返回值为 phase>=3,其含义为当整个线程执行了4个阶段后,程序终止。
  • forceTermination()方法,强制phaser进入终止态。

使用实例

对在CountDownLatch中的例子使用Phaser代替CountDownLatch进行改进:

package MyThread;

import java.util.concurrent.Phaser;

public class Match {

    // 模拟了100米赛跑,10名选手,只等裁判一声令下。当所有人都到达终点时,比赛结束。
    public static void main(String[] args) throws InterruptedException {

        final Phaser phaser=new Phaser() ;  
        // 十名选手 
        for (int index = ; index < ; index++) {
            phaser.register();
            new Thread(new player(phaser),"player"+index).start();
        }  
        System.out.println("Game Start");  
        //注销当前线程,比赛开始
        phaser.arriveAndDeregister();
        //是否非终止态一直等待
        while(!phaser.isTerminated()){          
        }
        System.out.println("Game Over");
    }
}
class player implements Runnable{

    private  final Phaser phaser ;  

    player(Phaser phaser){
        this.phaser=phaser;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {  
            // 第一阶段——等待创建好所有线程再开始
            phaser.arriveAndAwaitAdvance();  

            // 第二阶段——等待所有选手准备好再开始

            Thread.sleep((long) (Math.random() * )); 
            System.out.println(Thread.currentThread().getName() + " ready");   
            phaser.arriveAndAwaitAdvance();  

            // 第三阶段——等待所有选手准备好到达,到达后,该线程从phaser中注销,不在进行下面的阶段。
            Thread.sleep((long) (Math.random() * )); 
            System.out.println(Thread.currentThread().getName() + " arrived");   
            phaser.arriveAndDeregister(); 
        } catch (InterruptedException e) { 
            e.printStackTrace();          
        } 
    }
}
           

其他文章:http://whitesock.iteye.com/blog/1135457

http://blog.csdn.net/escaflone/article/details/10418651

其他同步辅助类:

Java并发编程-同步辅助类之Exchanger

Java并发编程-同步辅助类之CyclicBarrier

Java并发编程-同步辅助类之CountDownLatch

Java并发编程-同步辅助类之Semaphore