本文轉自: https://www.cnblogs.com/sxdcgaq8080/p/9456006.html
怎麼能有效保證高併發下的庫存和銷量的一致性呢?【具體實現方法:https://www.cnblogs.com/sxdcgaq8080/p/9454161.html】
====
那麼好,在這個接口中,開啓多線程模擬了多個用戶請求同時到達的狀況,現在想在多個線程都執行完了以後再統一返回結果給前臺,哪些請求成功了,哪些請求失敗了。
====
所以現在的需求是怎麼能實現 等待多個線程都執行完了以後再做事情~~~
===================================================================================================================================
其實想要實現這個需求:等待多個線程執行完了,再做事情。
有兩種方法,可以應對不同的情況:
分別是CountDownLatch和CyclicBarrier
===================================================================================================================================
CountDownLatch和CyclicBarrier簡單比較:
|
CountDownLatch |
CyclicBarrier |
---|---|---|
軟件包 |
java.util.concurrent |
java.util.concurrent |
適用情景 |
主線程等待多個工作線程結束 |
多個線程之間互相等待,直到所有線程達到一個障礙點(Barrier point) |
主要方法 |
CountDownLatch(int count) (主線程調用) 初始化計數 CountDownLatch.await (主線程調用) 阻塞,直到等待計數爲0解除阻塞 CountDownLatch.countDown 計數減一(工作線程調用) |
CyclicBarrier(int parties, Runnable barrierAction) //初始化參與者數量和障礙點執行Action,Action可選。由主線程初始化 CyclicBarrier.await() //由參與者調用 阻塞,直到所有線程達到屏障點 |
等待結束 |
各線程之間不再互相影響,可以繼續做自己的事情。不再執行下一個目標工作。 |
在屏障點達到後,允許所有線程繼續執行,達到下一個目標。可以重複使用CyclicBarrier |
異常 |
|
如果其中一個線程由於中斷,錯誤,或超時導致永久離開屏障點,其他線程也將拋出異常。 |
其他 |
|
如果BarrierAction不依賴於任何Party中的所有線程,那麼在任何party中的一個線程被釋放的時候,可以直接運行這個Action。 If(barrier.await()==2) { //do action } |
CountDownLatch 使用示例代碼:
主線程調用
工作線程調用
package com.sxd.swapping.utils;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
public class ThreadTest {
/**
* 主線程
*/
@Test
public void test(){
//開啓10個多線程
int threadCount = 10;
//所有線程阻塞,然後統一開始
CountDownLatch begin = new CountDownLatch(1);
//主線程阻塞,直到所有分線程執行完畢
CountDownLatch end = new CountDownLatch(threadCount);
//開始多線程
begin.countDown();
for (Integer i = 0; i < threadCount; i++) {
Runnable runnable = dealSomeThing(i,begin,end);
new Thread(runnable).start();
}
//多個線程都執行結束
try {
end.await();
System.out.println("多個線程都執行結束,可以做自己的事情了");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("多線程執行中出錯了,涼涼了!!!");
}
}
/**
* 工作線程
* 本方法 是在構造多線程要做的事情
*
* =====================可以做的事===================
* 當然可以傳入ConcurrentHashMap之類的線程安全的 類
* 來記錄線程中的處理結果之類的
* 最後 在多線程都執行完了以後 就可以對處理結果進行操作了
* ==================================================
*
* @param threadNum 當前線程編號
* @param begin
* @param end
* @return
*/
private Runnable dealSomeThing(int threadNum, CountDownLatch begin, CountDownLatch end){
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
System.out.println("線程"+threadNum+":--------------------->開始工作");
begin.await();
System.out.println("線程"+threadNum+"做具體的事情,比如去service調用 具體的方法做什麼操作之類的");
end.countDown();
System.out.println("線程"+threadNum+":--------------------->結束工作");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
return runnable;
}
}
最後實現的結果: