JAVA併發同步包之Phaser

   Java併發包中的Phaser功能強大,靈活的同時,也很複雜,不容易理解,Phaser類似於CyclicBarrier和CountDownLatch。相比於CyclicBarrier, Phaser主要有以下特徵

  • Phaser不但可以像CyclicBarrier一樣,可重複使用,而且能動態變更參與方數量數量,在 CyclicBarrier 中,在創建時,參與方數量是固定的。但是,在Phaser中,可以通過調用register()添加參與方,arriveAndDeregister()方法刪除參與方。
  • 一個Phaser有一個相關的phrase號,從0開始。當所有註冊方都到達一個Phaser時,Phaser進入下一個phrase,phrase號遞增1。phrase號的最大值爲Integer.MAX_VALUE(private static final int  MAX_PHASE= Integer.MAX_VALUE;)。最大值後,相位號以零爲起點重新開始。類似賽中的回合制。
  • Phaser有一個終止狀態。在終止狀態下,所有在Phaser上調用的同步方法都會立即返回,而不需要等待預處理
  • Phaser類的onAdvance()方法中寫代碼來指定一個phaser動作讓所有註冊方到達 phaser 時執行 phaser 動作。可以在個方法裏面返回true,讓Phaser不再執行。

用途:主要用於將一些併發任務分成若干個步驟

  例如一個表的數據存儲在三個庫中,統計一個字段的數據,可以寫三個三個線程從三個庫中讀,在主線程中phaser.arriveAndAwaitAdvance()方法,等待三個線程執行完後,進行統計。

實例

 我們用Phaser模擬一個跑步比賽,選手人數不定,比賽不分輪次,每一輪淘汰跑步時間超過一定時間的選手,直到最後一個勝出爲止。

Runner類繼承Thread類,代表每一個參賽者,,隨機生成一個1到5的整數,,用Thread.sleep()模擬參賽者跑步時長,每一輪都要等所有參賽者都到達後開始,當所有如果用時大於5秒,則淘汰。具體代碼:

import java.util.Random;
import java.util.concurrent.Phaser;

public class Runner extends Thread {
    private final String name;
    private final Phaser phaser;
    private static Random rand = new Random();

    public Runner(String name, Phaser phaser) {
        this.name = name;
        this.phaser = phaser;
    }

    @Override
    public void run() {
        while (!phaser.isTerminated()) {
            try {
                phaser.arriveAndAwaitAdvance();
                if(phaser.getArrivedParties() == 1) {
                    System.out.println(String.format("%s win", name));
                    phaser.arriveAndDeregister();
                    return;
                }
                int sleepTime = rand.nextInt(5) + 1;
                Thread.sleep(sleepTime * 1000);
                System.out.println(String.format("%s run Time:%d", name, sleepTime));
                if (sleepTime >= 5) {
                    phaser.arriveAndDeregister();
                    System.out.println(String.format("%s run Time:%d  out", name, sleepTime));
                    return;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

RunnerTest類裏實現了Phaser類,重載了onAdvance()方法。

import java.util.concurrent.Phaser;

public class RunnerTest {
    public static void main(String[] args) {
        final Integer PERSON_COUNT = 3;
        Phaser phaser = new Phaser() {
            @Override
            protected boolean onAdvance(int phase, int parties) {
                System.out.println(String.format("%d arrive phase :%d", parties, phase));
                if (parties == 1) {
                    return true;
                }
                System.out.println("------------------");
                return false;
            }
        };
        phaser.bulkRegister(PERSON_COUNT);
        for (int i = 0; i < PERSON_COUNT; i++) {
            Runner person = new Runner("Runner" + i, phaser);
            person.start();
        }

    }
}

運行結果:

3 arrive phase :0
------------------
Runner1 run Time:1
Runner2 run Time:4
Runner0 run Time:5
2 arrive phase :1
------------------
Runner0 run Time:5  out
Runner1 run Time:4
Runner2 run Time:5
1 arrive phase :2
Runner2 run Time:5  out
Runner1 win

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章