1. CountDownLatch
一個同步工具,允許一個或多個線程去等待其他線程中執行的一系列操作完成。
什麼意思呢?就是說,允許這個線程阻塞,直到,其他線程的所有操作都完成之後,在繼續執行。舉個例子。
public static void main(String[] args) throws InterruptedException {
final CountDownLatch downLatch = new CountDownLatch(5);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.err.println(i);
try {
Thread.sleep(1000);
downLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
downLatch.await();
System.err.println("結束了");
}
上面的例子 等五個線程都執行完畢之後,主線程纔會繼續執行。
用法如下:
- CountDownLatch(5) 後面的數字代表等待幾個線程完成
- 每當一個線程完成的時候,downLatch.countDown(),來使計數-1
- downLatch.await() ,直到計數爲0的時候,纔會執行他下面的邏輯。
2. CyclocBarrier
也是一個同步工具,允許一系列線程等待其中每一個都到達一個公共的障礙點,然後在繼續執行。並且,等待的線程都釋放之後,可以重用
作爲山溝溝裏的娃,受夠了坐車等人的折磨。舉個例子。
public static void main(String[] args){
final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.err.println("到齊了。可以開車了");
}
});
for (int i = 0; i < 5; i++) {
final int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
System.err.println("買票了"+ finalI);
try {
cyclicBarrier.await();
System.err.println("起飛了"+ finalI);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}).start();
}
}
輸出結果:
用法:
- CyclicBarrier(int parties, Runnable barrierAction) 構造函數中,參數一個是調用await的線程數,一個是到達障礙點之後的處理。
- cyclicBarrier.await() 表示我要等其他也到達,纔要繼續執行
3. Phaser
一個可重用的同步工具,可以實現提CyclicBarrier和CountDownLatch的功能,但是還有其他高級的功能。
3.1 實現CountDownLatch的功能
- CountDownLatch#countDown 由Phaser#arrive 代替
- CountDownLatch#await 由Phaser#awaitAdvance 代替
舉個例子:
final Phaser phaser = new Phaser(5);
for (int i = 0; i < 5; i++) {
final int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
System.err.println(finalI);
phaser.arrive();
}
}).start();
}
phaser.awaitAdvance(phaser.getPhase());
System.err.println("結束了");
3.2 實現CyclocBarrier的功能
雖然說能實現,但是還是比較弱。
- CyclicBarrier#await 由Phaser#arriveAndAwaitAdvance代替。
final Phaser phaser = new Phaser(5);
for (int i = 0; i < 5; i++) {
final int finalI = i;
new Thread(new Runnable() {
@Override
public void run() {
System.err.println("買票了"+ finalI);
phaser.arriveAndAwaitAdvance();
System.err.println("起飛了"+ finalI);
}
}).start();
}
3.3 高級功能
- 支持register和bulkRegister方法來調整任務數,arriveAndDeregister方法支持在任務到達的時候減少任務數
- arriveAndAwaitAdvance 表示任務到達並且等待其他任務到達
- 支持終止,如果onAdvance返回true,就會終止,如果註冊任務數爲0,也會終止。forceTermination方法會強制終止。
- 從它的構造函數來看,Phaser支持分層,Phaser(Phaser parent, int parties)。可以通過這些來構造出一個層次的Phaser
這些功能就不舉例子了。有興趣的同學可以去看下文檔。
參考資料
- JDK Phaser
- What’s New on Java 7 Phaser