Java執行緒之閉鎖
阿新 • • 發佈:2018-12-18
閉鎖是一種同步工具類,可以延遲執行緒的進度直到其到達終止狀態。閉鎖的作用相當於一扇門:在閉鎖到達結束狀態之前,這扇門一直是關閉的,並且沒有任何執行緒能通過,當到達結束狀態時,這扇門會開啟並允許所有的執行緒通過。當閉鎖到達結束狀態後,將不會再改變狀態,因此這扇門將永遠保持開啟狀態。閉鎖可以用來確保某些活動直到其他活動都完成後才繼續執行,例如:
- 確保某個計算再其需要的所有資源都被初始化之後才繼續執行。二元閉鎖(包括兩個狀態)可以用來表示“資源R已經被初始化”,而所有需要R的操作都必須先在這個閉鎖上等待。
- 確保某個服務在其依賴的所有其他服務都已經啟動之後才啟動。每個服務都有一個相關的二元閉鎖。每當啟動服務S時,將首先在S依賴的其他服務的閉鎖上等待,在所有依賴的服務都啟動後會釋放閉鎖S,這樣其他依賴S的服務才能繼續執行。
- 等待直到某個操作的所有參與者(例如,在多玩家遊戲中的所有玩家)都就緒時,閉鎖將到達結束狀態。
CountDownLatch
是一種靈活的閉鎖實現,可以在上述情況中使用,它可以使一個或多個執行緒等待一組事件發生。閉鎖狀包括一個計數器,該計數器被初始化為一個正數,表示需要等待的事件數量。countDown
方法遞減計數器,表示有一個事件已經發生了,而await
方法等待計數器達到零,這表示所有需要等待的事件都已經發生。如果計數器的值為非零,那麼await
會在一直阻塞直到計數器為零。或者等待中的執行緒中斷,或者等待超時。
public static long timeTTasks( int nThreads, final Runnable task) throws InterruptedException {
final CountDownLatch startGate = new CountDownLatch(1);//傳入計數器的大小
final CountDownLatch endGate = new CountDownLatch(nThreads);
for (int i = 0; i < nThreads; i++) {
Thread t = new Thread(new Runnable( ) {
@Override
public void run() {
try {
System.out.println("name:"+Thread.currentThread().getName()+"開始等待");
startGate.await();//等待
System.out.println("name:"+Thread.currentThread().getName()+"開始執行");
try {
task.run();
} finally {
endGate.countDown();//計數器減一
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
long start = System.nanoTime();
Thread.sleep(3000);
System.out.println("釋放startGate");
startGate.countDown();//計數器減一
endGate.await();//等待
long end = System.nanoTime();
return end - start;
}