前言
Java7為解決線程同步的問題除了提供鎖機制外闯参,增加了Semphore闷营、Exchanger、Phaser、CountDownLatch祸轮、CyclicBarrier四個工具類來解決多線程多任務(wù)同步的情景,本章介紹Phaser它也被稱為“階段器”廊敌,可以用它來控制多線程分階段共同完成的問題湾盒,本章后面會介紹一個具體的例子。
常用方法
這里我們將Phaser常用的方法進行分類介紹
- 設(shè)定任務(wù)數(shù)(這是官方解釋荐操,簡單的講比如我們指定任務(wù)數(shù)為3芜抒,那3個線程都運行到指定地方他們才會分別繼續(xù)往下執(zhí)行)
\\批量設(shè)置任務(wù)數(shù)
public int bulkRegister(int parties)
\\動態(tài)增加1個任務(wù)數(shù)
public int register()
\\減少一個任務(wù)數(shù)
public int arriveAndDeregister()
- 到達(dá)等待
\\線程執(zhí)行到此開始等待,滿足條件(任務(wù)數(shù)滿足)則繼續(xù)執(zhí)行
public int arriveAndAwaitAdvance()
\\ 線程執(zhí)行到此不用等待繼續(xù)執(zhí)行托启,但會讓任務(wù)數(shù)加1宅倒,然后會重置任務(wù)數(shù)。
public int arrive()
\\傳入的phase表示翻越幾個屏障屯耸,如果傳入的等于getPhase則等待
public int awaitAdvance(int phase)
\\可中斷的awaitAdvance
public int awaitAdvanceInterruptibly(int phase)拐迁;
\\可規(guī)定時間指定欄數(shù)未變,則拋出異常
public int awaitAdvanceInterruptibly(int phase,
long timeout, TimeUnit unit)
- 得到欄數(shù)以及任務(wù)數(shù)
\\當(dāng)前執(zhí)行到第幾個屏障
public final int getPhase()
\\得到注冊的任務(wù)數(shù)
public int getRegisteredParties()
\\已經(jīng)執(zhí)行的任務(wù)數(shù)
public int getArrivedParties()
\\還未執(zhí)行的任務(wù)數(shù)
public int getUnarrivedParties()
- 通過屏障時調(diào)用
\\該方法返回true則直接通過屏障 false則屏障繼續(xù)工作疗绣,要想實現(xiàn)自己的邏輯代碼需要復(fù)寫此方法
protected boolean onAdvance(int phase, int registeredParties)
- 關(guān)閉屏障
\\取消屏障
public void forceTermination()
\\phaser是否銷毀
public boolean isTerminated()
小例子
有10名運動員參加一場百米競賽线召,分為3階段:第一階段所有選手到達(dá)賽場、第二階段選手在起跑線就位持痰、完成比賽灶搜。
public class PharseDemo {
public static void main(String[] args) throws InterruptedException {
//10名運動員,每名運動員在同一時間點的開始
Phaser pharse = new Phaser(10) {
@Override
protected boolean onAdvance(int phase, int registeredParties) {
if(phase == 0) {
System.out.println("所有人員已經(jīng)到賽場");
}else if(phase == 1) {
System.out.println("所有人員準(zhǔn)備完畢工窍,開始比賽");
}else if(phase == 2) {
System.out.println("比賽結(jié)束");
}
return super.onAdvance(phase, registeredParties);
}
};
//創(chuàng)建10個線程
Runner run = new Runner(pharse);
Thread[] thread = new Thread[10];
for (int i = 0; i < 10; i++) {
thread[i] = new Thread(run);
}
Thread.sleep(3000);
for (int i = 0; i < 10; i++) {
thread[i].start();
}
}
}
class Runner implements Runnable{
private Phaser phaser;
Random random = new Random();
public Runner(Phaser phaser) {
super();
this.phaser = phaser;
}
@Override
public void run() {
try {
//第一階段 到達(dá)賽場 每個運動員情況不一樣
Thread.sleep(random.nextInt(3000));
System.out.println(Thread.currentThread().getName()+"已經(jīng)到達(dá)賽場");
phaser.arriveAndAwaitAdvance();
//第二階段 開始準(zhǔn)備
Thread.sleep(random.nextInt(3000));
System.out.println(Thread.currentThread().getName()+"已經(jīng)準(zhǔn)備好");
phaser.arriveAndAwaitAdvance();
//第二階段 到達(dá)終點
Thread.sleep(random.nextInt(3000));
System.out.println(Thread.currentThread().getName()+"已經(jīng)到達(dá)終點");
phaser.arriveAndAwaitAdvance();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
代碼中注釋很詳細(xì)割卖,這里就不贅述。通過Phaser的demo可以看出Phaser的諸多優(yōu)點:動態(tài)增加任務(wù)數(shù)患雏、得到程序執(zhí)行刀第幾階段等等......鹏溯,有了以上支持在多線程任務(wù)分階段執(zhí)行時就能更好的解決同步的問題了。