Java并发编程核心方法与框架-phaser的使用

arriveAndAwaitAdvance()方法

arriveAndAwaitAdvance()作用是当前线程已经到达屏障,在此等待一段时间,等条件满足后继续向下一个屏障执行。

public class PrintTools {
	public static Phaser phaser;
	public static void methodA() {
		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
		System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
	}
	
	public static void methodB() {
		try {
			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
			Thread.sleep(5000);
			phaser.arriveAndAwaitAdvance();
			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
			System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
			Thread.sleep(5000);
			phaser.arriveAndAwaitAdvance();
			System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public class ThreadA extends Thread {
	@Override
	public void run() {
		PrintTools.methodA();//执行A方法
	}
}

public class ThreadB extends Thread {
	@Override
	public void run() {
		PrintTools.methodA();//执行A方法
	}
}

public class ThreadC extends Thread {
	@Override
	public void run() {
		PrintTools.methodB();//执行B方法
	}
}

public class Main {
	public static void main(String[] args) {
		Phaser phaser = new Phaser(3);
		PrintTools.phaser = phaser;
		ThreadA a = new ThreadA();
		a.setName("A");
		a.start();
		ThreadB b = new ThreadB();
		b.setName("B");
		b.start();
		ThreadC c = new ThreadC();
		c.setName("C");
		c.start();
	}
}

程序运行结果如下:

A A1 begin 1469711023742
B A1 begin 1469711023742
C A1 begin 1469711023743
C A1 end 1469711028745
A A1 end 1469711028745
B A1 end 1469711028745
A A2 begin 1469711028745
C A2 begin 1469711028745
B A2 begin 1469711028745
B A2 end 1469711033748
C A2 end 1469711033748
A A2 end 1469711033748

A、B线程会等待C线程一起到达屏障点,然后一起继续向下执行。

对以上代码做如下修改:

public class PrintTools {
	public static Phaser phaser;
	public static void methodA() {
		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
		System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
	}
	
	public static void methodB() {
		try {
			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
			Thread.sleep(5000);
			phaser.arriveAndAwaitAdvance();
			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
			/* C提前退出比赛
			System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
			Thread.sleep(5000);
			phaser.arriveAndAwaitAdvance();
			System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
			*/
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
//其他代码保持不变

重新运行程序,控制台打印结果如下:

A A1 begin 1469711274416
B A1 begin 1469711274416
C A1 begin 1469711274417
B A1 end 1469711279421
C A1 end 1469711279421
A A1 end 1469711279421
B A2 begin 1469711279421
A A2 begin 1469711279421

A、B到达第二个屏障点后等不到C的到来,程序不结束,将会一直等下去。


arriveAndDeregister()方法

arriveAndDeregister()方法的作用是使线程退出比赛,并且使parties值减1

对以上代码做如下修改:

public class PrintTools {
	public static Phaser phaser;
	public static void methodA() {
		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
		System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
	}
	
	public static void methodB() {
		try {
			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
			Thread.sleep(5000);
			System.out.println("A:" + phaser.getRegisteredParties());
			phaser.arriveAndDeregister();//退出比赛
			System.out.println("B:" + phaser.getRegisteredParties());
			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
//其他代码保持不变

程序运行结果如下:

A A1 begin 1469711921794
B A1 begin 1469711921795
C A1 begin 1469711921795
A:3
B:2
B A1 end 1469711926799
C A1 end 1469711926799
A A1 end 1469711926799
B A2 begin 1469711926799
A A2 begin 1469711926800
B A2 end 1469711926800
A A2 end 1469711926800

此时程序可以正常结束。


onAdvance()方法
public class MyService {
	private Phaser phaser;
	public MyService(Phaser phaser) {
		super();
		this.phaser = phaser;
	}
	
	public void testMethod() {
		try {
			System.out.println("阶段1 Begin " + Thread.currentThread().getName() + System.currentTimeMillis());
			if (Thread.currentThread().getName().equals("B")) {
				Thread.sleep(5000);
			}
			phaser.arriveAndAwaitAdvance();
			System.out.println("阶段1 End " + Thread.currentThread().getName() + " end phase value=" + phaser.getPhase() + "   " + System.currentTimeMillis());
			/********/
			System.out.println("阶段2 Begin " + Thread.currentThread().getName() + System.currentTimeMillis());
			if (Thread.currentThread().getName().equals("B")) {
				Thread.sleep(5000);
			}
			phaser.arriveAndAwaitAdvance();
			System.out.println("阶段2 End " + Thread.currentThread().getName() + " end phase value=" + phaser.getPhase() + "   " + System.currentTimeMillis());
			/********/
			System.out.println("阶段3 Begin " + Thread.currentThread().getName() + System.currentTimeMillis());
			if (Thread.currentThread().getName().equals("B")) {
				Thread.sleep(5000);
			}
			phaser.arriveAndAwaitAdvance();
			System.out.println("阶段3 End " + Thread.currentThread().getName() + " end phase value=" + phaser.getPhase() + "   " + System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

//省略ThreadA、ThreadB
public class Main {
	public static void main(String[] args) {
		Phaser phaser = new Phaser(2){
			@Override
			protected boolean onAdvance(int phase, int registeredParties) {
				System.out.println("onAdvance 被" + Thread.currentThread().getName() + "调用 " + System.currentTimeMillis() + " phase value=" + phase + " registeredParties=" + registeredParties);
				return false;
				//返回true 不等待,Phaser呈无效/销毁的状态
				//返回false则Phaser继续工作
			}	
		};
		MyService service = new MyService(phaser);
		ThreadA a = new ThreadA(service);
		a.setName("A");
		a.start();
		ThreadB b = new ThreadB(service);
		b.setName("B");
		b.start();
	}
}

运行程序,控制台打印结果如下:

阶段1 Begin A1470103011668
阶段1 Begin B1470103011669
onAdvance 被B调用 1470103016670 phase value=0 registeredParties=2
阶段1 End B end phase value=1   1470103016670
阶段1 End A end phase value=1   1470103016670
阶段2 Begin A1470103016670
阶段2 Begin B1470103016670
onAdvance 被B调用 1470103021675 phase value=1 registeredParties=2
阶段2 End B end phase value=2   1470103021675
阶段2 End A end phase value=2   1470103021675
阶段3 Begin A1470103021675
阶段3 Begin B1470103021675
onAdvance 被B调用 1470103026677 phase value=2 registeredParties=2
阶段3 End B end phase value=3   1470103026677
阶段3 End A end phase value=3   1470103026677

onAdvance()在B线程到达屏障点时被调用。如果在onAdvance()方法中返回true,Phaser会被销毁。

对main函数中的代码做如下修改:

public class Main {
	public static void main(String[] args) {
		Phaser phaser = new Phaser(2){
			@Override
			protected boolean onAdvance(int phase, int registeredParties) {
				System.out.println("onAdvance 被" + Thread.currentThread().getName() + "调用 " + System.currentTimeMillis() + " phase value=" + phase + " registeredParties=" + registeredParties);
				return true;
				//返回true 不等待,Phaser呈无效/销毁的状态
				//返回false则Phaser继续工作
			}	
		};
		MyService service = new MyService(phaser);
		ThreadA a = new ThreadA(service);
		a.setName("A");
		a.start();
		ThreadB b = new ThreadB(service);
		b.setName("B");
		b.start();
	}
}

重新运行程序,控制台打印结果如下:

阶段1 Begin A1470103416899
阶段1 Begin B1470103416899
onAdvance 被B调用 1470103421901 phase value=0 registeredParties=2
阶段1 End B end phase value=-2147483647   1470103421901
阶段1 End A end phase value=-2147483647   1470103421901
阶段2 Begin B1470103421901
阶段2 Begin A1470103421901
阶段2 End A end phase value=-2147483647   1470103421901
阶段3 Begin A1470103421901
阶段3 End A end phase value=-2147483647   1470103421902
阶段2 End B end phase value=-2147483647   1470103426905
阶段3 Begin B1470103426905
阶段3 End B end phase value=-2147483647   1470103431907

arrive()方法

arrive()方法的作用是使parties值加1,并且不在屏障处等待,直接向下面的代码继续运行,并且充值Phaser类的计数。

public class Run {
	public static void main(String[] args) {
		Phaser phaser = new Phaser(2){
			@Override
			protected boolean onAdvance(int phase, int registeredParties) {
				System.out.println("到达了未通过!phase=" + phase + " registeredParties=" + registeredParties);
				return super.onAdvance(phase, registeredParties);
			}
		};
		System.out.println("A1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		phaser.arrive();
		System.out.println("A1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		System.out.println("A2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		phaser.arrive();
		System.out.println("A2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		//---------
		System.out.println("B1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		phaser.arrive();
		System.out.println("B1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		System.out.println("B2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		phaser.arrive();
		System.out.println("B2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		//---------
		System.out.println("C1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		phaser.arrive();
		System.out.println("C1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		System.out.println("C2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
		phaser.arrive();
		System.out.println("C2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
	}
}

运行程序,控制台打印结果如下:

A1,getPhase=0 getRegisteredParties=2 getArrivedParties=0
A1,getPhase=0 getRegisteredParties=2 getArrivedParties=1
A2,getPhase=0 getRegisteredParties=2 getArrivedParties=1
到达了未通过!phase=0 registeredParties=2
A2,getPhase=1 getRegisteredParties=2 getArrivedParties=0
B1,getPhase=1 getRegisteredParties=2 getArrivedParties=0
B1,getPhase=1 getRegisteredParties=2 getArrivedParties=1
B2,getPhase=1 getRegisteredParties=2 getArrivedParties=1
到达了未通过!phase=1 registeredParties=2
B2,getPhase=2 getRegisteredParties=2 getArrivedParties=0
C1,getPhase=2 getRegisteredParties=2 getArrivedParties=0
C1,getPhase=2 getRegisteredParties=2 getArrivedParties=1
C2,getPhase=2 getRegisteredParties=2 getArrivedParties=1
到达了未通过!phase=2 registeredParties=2
C2,getPhase=3 getRegisteredParties=2 getArrivedParties=0

方法arrive()的功能是使getArrivedParties()计数加1,不等待其他线程到达屏障。控制台多次出现getArrivedParties=0说明Phaser类经过屏障点后计数被重置。


arriveAdvance(int phase)方法的作用是:如果传入参数phase值和当前getPhase()方法返回值一样,则在屏障处等待,否则继续向下面运行。

public class ThreadA extends Thread {
	private Phaser phaser;
	public ThreadA(Phaser phaser) {
		super();
		this.phaser = phaser;
	}
	
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
	}
}

public class ThreadB extends Thread {
	private Phaser phaser;
	public ThreadB(Phaser phaser) {
		super();
		this.phaser = phaser;
	}
	
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
		phaser.arriveAndAwaitAdvance();
		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
	}
}

public class ThreadC extends Thread {
	private Phaser phaser;
	public ThreadC(Phaser phaser) {
		super();
		this.phaser = phaser;
	}
	
	@Override
	public void run() {
		try {
			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
			Thread.sleep(3000);
			phaser.awaitAdvance(0);//跨栏的栏数。不参与parties计数的操作,仅具有判断功能。
			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public class ThreadD extends Thread {
	private Phaser phaser;
	public ThreadD(Phaser phaser) {
		super();
		this.phaser = phaser;
	}
	
	@Override
	public void run() {
		try {
			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
			Thread.sleep(5000);
			phaser.arriveAndAwaitAdvance();
			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

public class Main {
	public static void main(String[] args) {
		Phaser phaser = new Phaser(3);
		ThreadA a = new ThreadA(phaser);
		a.setName("A");
		a.start();
		ThreadB b = new ThreadB(phaser);
		b.setName("B");
		b.start();
		ThreadC c = new ThreadC(phaser);
		c.setName("C");
		c.start();
		ThreadD d = new ThreadD(phaser);
		d.setName("D");
		d.start();
	}
}

程序运行结果如下:

A A1 begin 1470226617412
B A1 begin 1470226617412
C A1 begin 1470226617413
D A1 begin 1470226617414
C A1 end 1470226622416
B A1 end 1470226622416
A A1 end 1470226622416
D A1 end 1470226622416
posted @ 2016-07-14 20:26  商商-77  阅读(358)  评论(0编辑  收藏  举报