Java併發編程中級篇(六):併發階段性任務執行階段切換過程

Phaser類提供了一個onAdvance(),這個方法接收兩個int類型參數:分別是當前執行階段數以及註冊的參與者數量。方法返回一個布爾值,若是返回false代表Phaser中還有任務在執行,返回true表示這一階段Phaser執行完畢。java

Phaser對象進行階段切換的時候,在全部在arriveAndAwaitAdvance()方法裏休眠線程被喚醒以前,onAdvance()方法將被自動調用。onAdvance()方法返回布爾值代表Phaser終止與否,false表示沒有終止,於是縣城能夠繼續執行其餘階段。若是返回true,則Phaser仍然喚醒等待的線程,可是狀態已經改變爲終止狀態,因此繼續調用phaser的方法將當即返回,而且isTermination()方法也將返回true。併發

這個方法的默認實現以下,若是參與者數量是0返回true,不然返回false。可是咱們能夠經過繼承Phaser類類覆蓋這個方法。當從一個階段切換到另外一個階段是須要作一些操做,那麼咱們就這麼作。dom

protected boolean onAdvance(int phase, int registeredParties) {
  return registeredParties == 0;
}

咱們實現一個學生參加考試的例子,須要等待全部學生都到齊後才能參加考試,每一個學生都參加三場考試,而後考試結束。ide

首先咱們實現本身的Phaser類MyPhaser,這個類中咱們重寫onAdvance()方法,並定義每次階段切換執行的代碼。開始打印考試開始參加學生的數量,而後打印第一場考試結束信息,接着打印第二場考試結束信息,最後打印考試結束信息。前三個方法返回false,代表Phaser還在執行,最後一個方法返回true,代表Phaser執行結束。this

public class MyPhaser extends Phaser {
    @Override
    protected boolean onAdvance(int phase, int registeredParties) {
        switch (phase) {
            case 0:
                return studentsArrived();
            case 1:
                return finishFirstExercies();
            case 2:
                return finishSecondExercies();
            case 3:
                return finishExam();
            default:
                return true;
        }
    }

    private boolean studentsArrived() {
        System.out.printf("Phaser: The exam are going to start. The %d students are ready.\n",
                getRegisteredParties());
        return false;
    }

    private boolean finishFirstExercies() {
        System.out.printf("Phaser: All the studnets have finished the first exercies.\n");
        return false;
    }

    private boolean finishSecondExercies() {
        System.out.printf("Phaser: All the students have finished the second exercies.\n");
        return false;
    }

    private boolean finishExam() {
        System.out.printf("Phaser: All the students have finished the exam.\n");
        return true;
    }

}

定義Student類,使用phaser模擬四步操做 ,分別是考生到場,第一場考試,第二場考試,第三場考試。線程

public class Student implements Runnable{
    private Phaser phaser;

    public Student(Phaser phaser) {
        this.phaser = phaser;
    }

    @Override
    public void run() {
        System.out.printf("%s: Has arrived to the exam. %s\n", Thread.currentThread().getName(), new Date());
        phaser.arriveAndAwaitAdvance();
        System.out.printf("%s: is going to do the first exercise.\n", Thread.currentThread().getName());
        doExercise1();
        System.out.printf("%s: has done the first exercise.\n", Thread.currentThread().getName());
        phaser.arriveAndAwaitAdvance();
        System.out.printf("%s: is going to do the second exercise.\n", Thread.currentThread().getName());
        doExercise2();
        System.out.printf("%s: has done the second exercise.\n", Thread.currentThread().getName());
        phaser.arriveAndAwaitAdvance();
        System.out.printf("%s: is going to do the third exercise.\n", Thread.currentThread().getName());
        doExercise3();
        System.out.printf("%s: has finished the exam.\n", Thread.currentThread().getName());
        phaser.arriveAndAwaitAdvance();
    }

    private void doExercise1() {
        long duration = (long)(Math.random() * 20);
        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void doExercise2() {
        long duration = (long)(Math.random() * 20);
        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void doExercise3() {
        long duration = (long)(Math.random() * 20);
        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

實現主方法類,在這裏咱們建立5個考生線程,並啓動它們。咱們並無在Phaser初始化的時候指定併發線程數量,而是在建立線程的時候使用register()方法來註冊到Phaser上。日誌

public class Main{
    public static void main(String[] args) {
        Phaser phaser = new MyPhaser();

        Student[] students = new Student[5];
        Thread[] threads = new Thread[5];

        for (int i = 0; i < 5; i++) {
            students[i] = new Student(phaser);
            phaser.register();
            threads[i] = new Thread(students[i], "Student-" + i);
        }

        for (int i = 0; i < 5; i++) {
            threads[i].start();
        }

        for (int i = 0; i < 5; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.printf("Main: The phaser has finished: %s.\n", phaser.isTerminated());
    }
}

查看日誌code

Student-4: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-0: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-2: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-1: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-3: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Phaser: The exam are going to start. The 5 students are ready.
Student-3: is going to do the first exercise.
Student-0: is going to do the first exercise.
Student-0: has done the first exercise.
Student-4: is going to do the first exercise.
Student-2: is going to do the first exercise.
Student-1: is going to do the first exercise.
Student-1: has done the first exercise.
Student-4: has done the first exercise.
Student-3: has done the first exercise.
Student-2: has done the first exercise.
Phaser: All the studnets have finished the first exercies.
Student-2: is going to do the second exercise.
Student-0: is going to do the second exercise.
Student-4: is going to do the second exercise.
Student-1: is going to do the second exercise.
Student-1: has done the second exercise.
Student-3: is going to do the second exercise.
Student-2: has done the second exercise.
Student-0: has done the second exercise.
Student-4: has done the second exercise.
Student-3: has done the second exercise.
Phaser: All the students have finished the second exercies.
Student-3: is going to do the third exercise.
Student-2: is going to do the third exercise.
Student-1: is going to do the third exercise.
Student-0: is going to do the third exercise.
Student-4: is going to do the third exercise.
Student-4: has finished the exam.
Student-0: has finished the exam.
Student-2: has finished the exam.
Student-1: has finished the exam.
Student-3: has finished the exam.
Phaser: All the students have finished the exam.
Main: The phaser has finished: true.

咱們嘗試把第一場考試執行完畢後的onAdvance方法返回值改成true試試結果,能夠看到全部線程執行完第二場考試以後直接就開始執行第三場考試了,並無等待其餘線程都執行完畢第二場考試。對象

Student-4: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-3: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-1: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-2: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-0: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Phaser: The exam are going to start. The 5 students are ready.
Student-0: is going to do the first exercise.
Student-2: is going to do the first exercise.
Student-4: is going to do the first exercise.
Student-3: is going to do the first exercise.
Student-1: is going to do the first exercise.
Student-1: has done the first exercise.
Student-0: has done the first exercise.
Student-2: has done the first exercise.
Student-4: has done the first exercise.
Student-3: has done the first exercise.
Phaser: All the studnets have finished the first exercies.
Student-3: is going to do the second exercise.
Student-2: is going to do the second exercise.
Student-0: is going to do the second exercise.
Student-1: is going to do the second exercise.
Student-4: is going to do the second exercise.
Student-3: has done the second exercise.
Student-3: is going to do the third exercise.
Student-1: has done the second exercise.
Student-1: is going to do the third exercise.
Student-0: has done the second exercise.
Student-0: is going to do the third exercise.
Student-0: has finished the exam.
Student-2: has done the second exercise.
Student-2: is going to do the third exercise.
Student-4: has done the second exercise.
Student-4: is going to do the third exercise.
Student-3: has finished the exam.
Student-2: has finished the exam.
Student-1: has finished the exam.
Student-4: has finished the exam.
Main: The phaser has finished: true.
相關文章
相關標籤/搜索