CountDownLatch 使用(模拟一场比赛)
java.util.concurrency中的CountDownLatch,主要用于等待一个或多个其他线程完成任务。CountDownLatch在初始化时,会被赋一个整数,每次执行countDown()方法,该整数都会减一,直至到0,这一过程不可逆转。其await()方法会在该整数不为0时当前线程阻塞,为0时当前线程进行下去。阻塞时,其他线程得到执行。
下面是一个普通的案例:
Player
import java.util.Random; import java.util.concurrent.CountDownLatch; public class Player implements Runnable { private CountDownLatch begin; private CountDownLatch end; private String playerNO; public Player(String playerNO, CountDownLatch begin, CountDownLatch end) { this.playerNO = playerNO; this.begin = begin; this.end = end; } @Override public void run() { // 等待枪响 try { begin.await(); long timeUsed = new Random().nextInt(10000); Thread.sleep(timeUsed); System.out.println("运动员" + playerNO + "耗时" + timeUsed + "完成比赛"); } catch (InterruptedException e) { e.printStackTrace(); } finally { end.countDown(); } } }
OlympicsGame
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class OlympicsGame { private static final int PLAYER_SIZE = 5; private CountDownLatch begin; private CountDownLatch end; public CountDownLatch getBegin() { return begin; } public void setBegin(CountDownLatch begin) { this.begin = begin; } public CountDownLatch getEnd() { return end; } public void setEnd(CountDownLatch end) { this.end = end; } public OlympicsGame() { begin = new CountDownLatch(1); end = new CountDownLatch(PLAYER_SIZE); } public static void main(String[] args) { // 举办一场比赛 OlympicsGame olympic = new OlympicsGame(); // 设定比赛开始,枪声 CountDownLatch begin = olympic.getBegin(); // 所有运动员结束比赛,才算结束比赛 CountDownLatch end = olympic.getEnd(); // 运动员进场,并编号,等待枪响 Player[] players = new Player[PLAYER_SIZE]; ExecutorService ex = Executors.newFixedThreadPool(PLAYER_SIZE); for (int i = 0; i < 5; i++) { players[i] = new Player("NO" + (i + 1), begin, end); ex.submit(players[i]); } // 枪响 begin.countDown(); try { // 等待所有运动员到达终点 end.await(); System.out.println("比赛结束,所有运动员完成比赛"); } catch (InterruptedException e) { e.printStackTrace(); } } }
某次执行结果是: