1. 程式人生 > >java多執行緒之Phaser

java多執行緒之Phaser

java多執行緒技術提供了Phaser工具類,Phaser表示“階段器”,用來解決控制多個執行緒分階段共同完成任務的情景問題。其作用相比CountDownLatch和CyclicBarrier更加靈活,例如有這樣的一個題目:5個學生一起參加考試,一共有三道題,要求所有學生到齊才能開始考試,全部同學都做完第一題,學生才能繼續做第二題,全部學生做完了第二題,才能做第三題,所有學生都做完的第三題,考試才結束。分析這個題目:這是一個多執行緒(5個學生)分階段問題(考試考試、第一題做完、第二題做完、第三題做完),所以很適合用Phaser解決這個問題。

 

實現程式碼

import java.util.concurrent.Phaser;
 
/***
 *  下面說說Phaser的高階用法,在Phaser內有2個重要狀態,分別是phase和party。
 *  phase就是階段,初值為0,當所有的執行緒執行完本輪任務,同時開始下一輪任務時,
 *  意味著當前階段已結束,進入到下一階段,phase的值自動加1。party就是執行緒,
 *  party=4就意味著Phaser物件當前管理著4個執行緒。Phaser還有一個重要的方法經常需要被過載,
 *  那就是boolean onAdvance(int phase, int registeredParties)方法。此方法有2個作用:
 *  1、當每一個階段執行完畢,此方法會被自動呼叫,因此,過載此方法寫入的程式碼會在每個階段執行完畢時執行,
 *  相當於CyclicBarrier的barrierAction。
 *  2、當此方法返回true時,意味著Phaser被終止,因此可以巧妙的設定此方法的返回值來終止所有執行緒。
 * @author liujun
 */
public class MyPhaser extends Phaser {
 
	@Override
	protected boolean onAdvance(int phase, int registeredParties) {	//在每個階段執行完成後回撥的方法
		
		switch (phase) {
		case 0:
			return studentArrived();
		case 1:
			return finishFirstExercise();
		case 2:
			return finishSecondExercise();
		case 3:
			return finishExam();
		default:
			return true;
		}
		
	}
	
	private boolean studentArrived(){
		System.out.println("學生準備好了,學生人數:"+getRegisteredParties());
		return false;
	}
	
	private boolean finishFirstExercise(){
		System.out.println("第一題所有學生做完");
		return false;
	}
	
	private boolean finishSecondExercise(){
		System.out.println("第二題所有學生做完");
		return false;
	}
	
	private boolean finishExam(){
		System.out.println("第三題所有學生做完,結束考試");
		return true;
	}
	
}

import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
 
public class StudentTask implements Runnable {
 
	private Phaser phaser;
	
	public StudentTask(Phaser phaser) {
		this.phaser = phaser;
	}
 
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()+"到達考試");
		phaser.arriveAndAwaitAdvance();
		
		System.out.println(Thread.currentThread().getName()+"做第1題時間...");
		doExercise1();
		System.out.println(Thread.currentThread().getName()+"做第1題完成...");
		phaser.arriveAndAwaitAdvance();
		
		System.out.println(Thread.currentThread().getName()+"做第2題時間...");
		doExercise2();
		System.out.println(Thread.currentThread().getName()+"做第2題完成...");
		phaser.arriveAndAwaitAdvance();
		
		System.out.println(Thread.currentThread().getName()+"做第3題時間...");
		doExercise3();
		System.out.println(Thread.currentThread().getName()+"做第3題完成...");
		phaser.arriveAndAwaitAdvance();
	}
 
	private void doExercise1() {
		long duration = (long)(Math.random()*10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private void doExercise2() {
		long duration = (long)(Math.random()*10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	private void doExercise3() {
		long duration = (long)(Math.random()*10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}
/**
 * 題目:5個學生參加考試,一共有三道題,要求所有學生到齊才能開始考試
 * ,全部做完第一題,才能繼續做第二題,後面類似。
 * 
 * Phaser有phase和party兩個重要狀態,
 * phase表示階段,party表示每個階段的執行緒個數,
 * 只有每個執行緒都執行了phaser.arriveAndAwaitAdvance();
 * 才會進入下一個階段,否則阻塞等待。
 * 例如題目中5個學生(執行緒)都條用phaser.arriveAndAwaitAdvance();就進入下一題
 * @author liujun
 */
public class Main {
 
	public static void main(String[] args) {
		MyPhaser phaser = new MyPhaser();
		StudentTask[] studentTask = new StudentTask[5];
		for (int i = 0; i < studentTask.length; i++) {
			studentTask[i] = new StudentTask(phaser);
			phaser.register();	//註冊一次表示phaser維護的執行緒個數
		}
		
		Thread[] threads = new Thread[studentTask.length];
		for (int i = 0; i < studentTask.length; i++) {
			threads[i] = new Thread(studentTask[i], "Student "+i);
			threads[i].start();
		}
		
		//等待所有執行緒執行結束
		for (int i = 0; i < studentTask.length; i++) {
			try {
				threads[i].join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		System.out.println("Phaser has finished:"+phaser.isTerminated());
		
	}
	
}

結果

Student 0到達考試
Student 1到達考試
Student 4到達考試
Student 2到達考試
Student 3到達考試
學生準備好了5
Student 2做第1題時間...
Student 0做第1題時間...
Student 1做第1題時間...
Student 4做第1題時間...
Student 3做第1題時間...
Student 2做第1題完成...
Student 3做第1題完成...
Student 1做第1題完成...
Student 0做第1題完成...
Student 4做第1題完成...
第一題所有學生做完
Student 3做第2題時間...
Student 0做第2題時間...
Student 4做第2題時間...
Student 1做第2題時間...
Student 2做第2題時間...
Student 3做第2題完成...
Student 2做第2題完成...
Stud ent 0做第2題完成...
Student 1做第2題完成...
Student 4做第2題完成...
第二題所有學生做完
Student 0做第3題時間...
Student 3做第3題時間...
Student 2做第3題時間...
Student 4做第3題時間...
Student 1做第3題時間...
Student 1做第3題完成...
Student 0做第3題完成...
Student 2做第3題完成...
Student 3做第3題完成...
Student 4做第3題完成...
第三題所有學生做完,結束考試
Phaser has finished:true