简介
Phaser由java7中推出,是java7中新增的一个使用同步工具,在功能上面它与CyclicBarrier、CountDownLatch有些重叠,但是它提供了更加灵活、强大的用法。
CyclicBarrier,允许一组线程互相等待,直到到达某个公共屏障点。它提供的await()可以实现让所有参与者在临界点到来之前一直处于等待状态。
CountDownLatch,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。它提供了await()、countDown()两个方法来进行操作。
在Phaser中,它把多个线程协作执行的任务划分为多个阶段,编程时需要明确各个阶段的任务,每个阶段都可以有任意个参与者,线程都可以随时注册并参与到某个阶段。
Phaser代替CountDownLatch
package com.example.demo.three.untils.phaser;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
/**
* @Author: CYM
* @Description:
* @Data: 2017/10/14 21:01
*/
public class PhaserTest1 {
public static void main(String[] args) {
final Phaser phaser = new Phaser(6);
for (int i = 1; i <= 5; i++) {
new Task(phaser).start();
}
phaser.arriveAndAwaitAdvance();
System.out.println("===========");
}
static class Task extends Thread {
private final Phaser phaser;
Task(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
System.out.println("working: +" + Thread.currentThread().getName()+"--");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
phaser.arriveAndAwaitAdvance();
}
}
}
Phaser代替CyclicBarrier
package com.example.demo.three.untils.phaser;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
/**
* @Author: CYM
* @Description:
* @Data: 2017/10/14 21:01
*/
public class PhaserTest2 {
/**
* 所有线程执行完A,再执行B,所有线程执行完B后,再执行C.........
* 类似 : CyclicBarrier
* @param args
*/
public static void main(String[] args) {
final Phaser phaser = new Phaser(3);
for (int i = 1; i <= 3; i++) {
new Task(phaser).start();
}
}
static class Task extends Thread {
private final Phaser phaser;
Task(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
try {
System.out.println( Thread.currentThread().getName()+"-----A-----start");
TimeUnit.SECONDS.sleep(2);
System.out.println( Thread.currentThread().getName()+"-----A-----end");
phaser.arriveAndAwaitAdvance();
System.out.println( Thread.currentThread().getName()+"-----B-----start");
TimeUnit.SECONDS.sleep(2);
System.out.println( Thread.currentThread().getName()+"-----B-----end");
phaser.arriveAndAwaitAdvance();
System.out.println( Thread.currentThread().getName()+"-----C-----start");
TimeUnit.SECONDS.sleep(2);
System.out.println( Thread.currentThread().getName()+"-----C-----end");
phaser.arriveAndAwaitAdvance();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Phaser一些方法
package com.example.demo.three.untils.phaser;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
/**
* @Author: CYM
* @Description:
* @Data: 2017/10/14 21:01
*/
public class Test {
/**
* @param args
*/
public static void main(String[] args) throws InterruptedException {
final Phaser phaser = new Phaser(1);
//getPhase()获取到达第几个屏障 Returns the current phase number.
System.out.println("getPhase: " + phaser.getPhase()); //0
phaser.arriveAndAwaitAdvance();
System.out.println("getPhase: " + phaser.getPhase()); //1
phaser.arriveAndAwaitAdvance();
System.out.println("getPhase: " + phaser.getPhase()); //2
/**-------------------------------------------------------------------------------------------------*/
//getRegisteredParties获取注册partis的数量 Returns the number of parties registered at this phaser
System.out.println("getRegisteredParties: " + phaser.getRegisteredParties());//1
//register()动态添加一个partis
phaser.register();
System.out.println("getRegisteredParties: " + phaser.getRegisteredParties());//2
//bulkRegister()批量增加partis
phaser.bulkRegister(2);
System.out.println("getRegisteredParties: " + phaser.getRegisteredParties());//4
/**-------------------------------------------------------------------------------------------------*/
final Phaser phaser3 = new Phaser(4);
phaser3.arriveAndDeregister();//parties减少一个
System.out.println("getRegisteredParties1: " + phaser3.getRegisteredParties());//3
/**-------------------------------------------------------------------------------------------------*/
final Phaser phaser2 = new Phaser(5);
for (int i = 1; i <= 3; i++) {
new Task(phaser2).start();
}
TimeUnit.SECONDS.sleep(2);
//getArrivedParties()已被使用partis
//getUnarrivedParties()未被使用partis
System.out.println("getArrivedParties:" + phaser2.getArrivedParties()); //3
System.out.println("getUnarrivedParties:" + phaser2.getUnarrivedParties());//2
}
static class Task extends Thread {
private final Phaser phaser;
Task(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
phaser.arriveAndAwaitAdvance();
}
}
}
onAdvance(int phase, int registeredParties)
package com.example.demo.three.untils.phaser;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
/**
* @Author: CYM
* @Description:
* @Data: 2017/10/14 21:01
*/
public class Test2 {
/**
* @param args
*/
public static void main(String[] args) throws InterruptedException {
final Phaser phaser4 = new Phaser(3){
/**
* @param phase 到达第几个屏障
* @param registeredParties 注册Parties数量
* @return true 第一次phaser.arriveAndAwaitAdvance()后,调用此方法,之后Phaser呈无效/销毁状态
* false 多次调用phaser.arriveAndAwaitAdvance(),Phaser继续工作
*/
@Override
protected boolean onAdvance(int phase, int registeredParties) {
System.err.println("进入onAdvance:" + phase+registeredParties);
return true;
}
};
for (int i = 1; i <= 3; i++) {
new Task(phaser4).start();
}
}
static class Task extends Thread {
private final Phaser phaser;
Task(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"---1---");
TimeUnit.SECONDS.sleep(2);
phaser.arriveAndAwaitAdvance();
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"===2===");
System.out.println("是否销毁:" + phaser.isTerminated());
if (Thread.currentThread().getName().equals("Thread-0")){
TimeUnit.SECONDS.sleep(10);
}
phaser.arriveAndAwaitAdvance();
TimeUnit.SECONDS.sleep(1);
System.out.println("*********");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
arrive()
跟arriveAndAwaitAdvance()相比,不用等待。
public static void main(String[] args) throws InterruptedException {
final Phaser phaser = new Phaser(2);
new Thread(phaser::arrive).start(); //Arrives at this phaser,without waiting for others to arrive.
System.out.println("*********");
new Thread(phaser::arriveAndAwaitAdvance).start();
System.out.println("*********");
}
awaitAdvance(phase)
如果当前传入参数phase和getPhase()方法返回的值一样。则在屏障处等待,直到两者值不一样。不可被打中断。并不参与parties计数。
public class Test4 {
/**
* @param args
*/
public static void main(String[] args) throws InterruptedException {
final Phaser phaser = new Phaser(4);
for (int i = 0; i <= 3; i++) {
new Task(phaser).start();
}
final int phase = phaser.getPhase();
/**awaitAdvance(phase):如果当前传入参数phase和getPhase()方法
* 返回的值一样。则在屏障处等待,直到两者值不一样。不可被打中断
*
* 分析:传入参数phase=0,phaser.awaitAdvance(0)会一直等待,当第一次所有线程
* 执行到phaser.arriveAndAwaitAdvance(),这时phaser.getPhase()为1,phaser.awaitAdvance(0)
* 放行。
*
* 输出结果: *****1****1
*****1****1
*****1****1
*****1****1
*********0
*****2****2
*****2****2
*****2****2
*****2****2
*/
phaser.awaitAdvance(phase);
System.out.println("*********" + phase);
/**----------------------------------------*/
/**
* awaitAdvance(int phase) 并不参与parties计数
*
* 结果:从输出结果可以看到:phaser1.getArrivedParties()为0
*/
final Phaser phaser1 = new Phaser(4);
new Thread(()->phaser1.awaitAdvance(0)).start();
TimeUnit.SECONDS.sleep(20);
System.err.println(phaser1.getArrivedParties());
}
static class Task extends Thread {
private final Phaser phaser;
Task(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(1);
phaser.arriveAndAwaitAdvance();
System.out.println("*****1****"+phaser.getPhase());
TimeUnit.SECONDS.sleep(1);
phaser.arriveAndAwaitAdvance();
System.out.println("*****2****"+phaser.getPhase());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
awaitAdvanceInterruptibly(int phase)可被中断.
awaitAdvanceInterruptibly(int phase,long timeout, TimeUnit unit) 最多等待指定时间,可中断.
forceTermination()
public static void main(String[] args) throws InterruptedException {
final Phaser phaser = new Phaser(3);
new Thread(phaser::arriveAndAwaitAdvance).start();
TimeUnit.SECONDS.sleep(3);
System.out.println(phaser.isTerminated());
phaser.forceTermination();
System.out.println(phaser.isTerminated());
}