今天在controller中寫一個接口用來測試模擬多個請求同時到達 下訂單的情況,
怎么能有效保證高並發下的庫存和銷量的一致性呢?【具體實現方法: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; } }
最后實現的結果:
=========================================================================================
CyclicBarrier使用示例代碼:
現在還沒用到,空閑了再補充