問題背景:
問題一:
java多線程,A、B、C、D統計4個盤大小,統計完後第5個人彙總。
問題二:
比如一個團隊賽跑遊戲,最後要計算團隊賽跑的成績,主線程計算最後成績,要等到所有團隊成員跑完,方可計算總成績。
java.util.concurrent.CountDownLatch
你可以向 CountDownLatch 對象設定一個初始計數值,任何在這個對象上調用 await() 的方法都将阻塞,直到這個計數值為0。其他任務在結束其工作時,可以在該對象上調用 countDown() 來減小這個數值,這個方法不會阻塞線程。 CountDownLatch 被設計為隻觸發一次,計數值不能被重置。如果你需要能夠重置計數值的版本,則可以使用 CyclicBarrier .
CountDownLatch 的典型用法時将一個程式分成n個互相獨立的可解決任務,并建立值為n的CountDownLatch。每當任務完成時,都會在這個鎖存儲器上調用countDown()方法。等待問題被解決的任務在這個鎖存儲器上調用await()。将它們自己攔住,直到存儲器計數結束。
示例1:通用代碼示例
import java.util.concurrent.CountDownLatch;
/**
* 比如一個團隊賽跑遊戲,最後要計算團隊賽跑的成績,主線程計算最後成績,要等到所有
* 團隊成員跑完,方可計算總成績。
*
* 題目2:統計4個盤子的大小,統計完後交給第五個人彙總
*/
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(4);
//四個人賽跑,這4個可以寫一個for循環
new Thread(new Worker(startSignal, doneSignal)).start();
new Thread(new Worker(startSignal, doneSignal)).start();
new Thread(new Worker(startSignal, doneSignal)).start();
new Thread(new Worker(startSignal, doneSignal)).start();
System.out.println("這裡放計數前自己的代碼...");//由于startSignal是1,上邊的4個線程還不能執行
startSignal.countDown(); // startSignal=0,線程可以開始執行了
//doSomethingElse();
System.out.println("計數後的代碼...這是主線程...和上邊4個線程混在一起的...");
doneSignal.await(); // 判斷上邊4個是否執行完了,如果是,則允許下邊的代碼執行
//開始執行另外一個任務
System.out.println("開始執行其他任務...");
}
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
@Override
public void run() {
try {
startSignal.await(); //startSignal的計數到0了嗎?到0了,才能執行
doWork();
doneSignal.countDown();
} catch (InterruptedException ex) {
}
}
void doWork() {
System.out.println("正在統計中...");
}
}
//結果
這裡放計數前自己的代碼...
計數後的代碼...這是主線程...和上邊4個線程混在一起的...
正在統計中...
正在統計中...
正在統計中...
正在統計中...
開始執行其他任務...