Java的併發控制中,有個很有用的類叫CountDownLatch,直譯就是倒數鎖,構造時傳入一個初始值,其他線程都可以控制計數器-1,當計數減至0時觸發特定的事件。
demo是最好的老師,下面貼上代碼,看看用他如何模擬一個運動會的跑步比賽吧。
運動員類:
import java.util.concurrent.CountDownLatch;
public class Player implements Runnable {
private int id;//運動員編號
private CountDownLatch begin;//開始鎖
private CountDownLatch end;//結束鎖
public Player(int id,CountDownLatch begin,CountDownLatch end) {
this.id=id;
this.begin=begin;
this.end=end;
}
@Override
public void run() {
try {
begin.await();//等待比賽開始
long time=System.currentTimeMillis();
Thread.sleep((long) (Math.random()*5000));//模擬具體一個運動員跑全程花費時間,最長是5秒
System.out.println("運動員 "+id+" 到達,用時 "+(System.currentTimeMillis()-time));
} catch (Exception e) {
System.out.println(e.getMessage());
}finally{
end.countDown();//該運動員到達終點,通知latch將計數器減一
}
}
}
然後是主類:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class LatchDemo {
public static void main(String[] args) throws InterruptedException {
Player[] players=new Player[10];//10個運動員參賽
CountDownLatch begin=new CountDownLatch(1);//比賽開始的計數鎖,由比賽裁判控制
CountDownLatch end=new CountDownLatch(players.length);//比賽結束的計數鎖,所有運動員跑完後停止
for(int i=0;i<players.length;i++){//爲每個運動員編號,並安排到同一個比賽中(公用一樣的開始與結束計數鎖)
players[i]=new Player(i, begin, end);
}
ExecutorService executorService=Executors.newFixedThreadPool(players.length);
for(Player p:players){
executorService.execute(p);
}//各個運動員都準備就緒了(線程都執行起來了,但這些線程都進入等待開始的CountDownLatch中)
System.out.println("比賽開始~");
long time=System.currentTimeMillis();
begin.countDown();//裁判員吹哨,讓所有的運動員都開始跑了
end.await();//裁判等待所有運動員跑完
System.out.println("比賽結束,用時"+(System.currentTimeMillis()-time));
}
}
下面是運行結果:
比賽開始~
運動員 3 到達,用時 297
運動員 9 到達,用時 336
運動員 8 到達,用時 535
運動員 0 到達,用時 1061
運動員 2 到達,用時 1464
運動員 5 到達,用時 2128
運動員 4 到達,用時 2160
運動員 1 到達,用時 2883
運動員 7 到達,用時 4461
運動員 6 到達,用時 4959
比賽結束,用時4959