1. 背景
CountDownLatch類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。
用給定的計數 初始化 CountDownLatch。由于調用了 countDown() 方法,是以在目前計數到達零之前,await 方法會一直受阻塞。之後,會釋放所有等待的線程,await 的所有後續調用都将立即傳回。這種現象隻出現一次——計數無法被重置。
2. 示範代碼
下面代碼示範了如果撲克遊戲一桌人都到齊了,則翻底牌:
package com.clzhang.sample.thread;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SyncCountDownLatch {
class PokerPlayer implements Runnable {
private final String[] POINTS = new String[]{"A", "2", "3", "4", "5", "6", "7", "8", "9",
"10", "J", "Q", "K",};
private String name;
private CountDownLatch countDown;
public PokerPlayer(String name, CountDownLatch countDown) {
this.name = name;
this.countDown = countDown;
}
@Override
public void run() {
try {
Thread.sleep((long) (Math.random() * 5000));
// 随機抽一張牌
Random random = new Random();
String myPoint = POINTS[random.nextInt(13)];
System.out.println(name + "ready!");
// 準備就緒,等待其它玩家也就緒
countDown.countDown();
countDown.await();
// 玩家都就緒了,翻底牌
System.out.println(name + ":" + myPoint);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final int PER_TABLE_PLAYERS = 4; // 多少人夠開一桌的
CountDownLatch countDown = new CountDownLatch(PER_TABLE_PLAYERS);
SyncCountDownLatch ins = new SyncCountDownLatch();
ExecutorService executorPool = Executors.newFixedThreadPool(PER_TABLE_PLAYERS);
for(int i=0; i<PER_TABLE_PLAYERS; i++) {
executorPool.execute(ins.new PokerPlayer(i +"号玩家", countDown));
}
executorPool.shutdown();
}
}
輸出
3号玩家ready!
0号玩家ready!
1号玩家ready!
2号玩家ready!
3号玩家:5
0号玩家:3
1号玩家:7
2号玩家:6