CountDownLatch和CyclicBarrier的區別
1. 官方概念
CyclicBarrier
字面意思迴環柵欄,通過它可以實現讓一組執行緒等待至某個狀態之後再全部同時執行。叫做迴環是因為當所有等待執行緒都被釋放以後,CyclicBarrier可以被重用。我們暫且把這個狀態就叫做barrier,當呼叫await()方法之後,執行緒就處於barrier了。
CountDownLatch
一個執行緒(或者多個), 等待另外N個執行緒完成某個事情之後才能執行
2. 個人理解
CyclicBarrier
想想柵欄的意思,有點像切面的意思。
場景如下:
1)就比如假設有隻有的一個場景:每個執行緒代表一個跑步運動員,當運動員都準備好後,才一起出發,只要有一個人沒有準備好,大家都等待. 功能如下圖所示。
2)玩家0正在玩第一關...玩家3正在玩第一關...玩家2正在玩第一關...玩家1正在玩第一關...所有玩家進入第二關
從上面圖可以看出CyclicBarrier 也可以作為計數器用
CountDownLatch
是計數器, 執行緒完成一個就記一個, 就像 報數一樣, 只不過是遞減的. 結構/功能如下圖所示
3. 實際列子
1)需求: 有20個執行緒需要執行, 單執行緒池中最多隻能有5個執行緒執行, 需要在所有執行緒執行完之後再進行其他操作
2)需求: 將Case 自動化儲存到測試用例管理工具中,每個Case也有可能使用別的Case當做前提條件,若需要將Case儲存到TestRail 中需要以下步驟:
儲存每個Case的流程如下:
A:儲存Case的詳細資訊到testrail
B: 儲存Case的前提條件(需要其他Case的CaseID)到testrail.
C: 儲存Case的後續條件(需要其他Case的CaseID)到testrail.
這就說明。儲存Case的前提條件必須在儲存所有Case的詳細資訊以後獲取到CaseID, 再儲存前提條件到每個Case中
分析: 使用CyclicBarrier 實現
詳細程式碼如下
import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; public class CaseToTestRail implements Runnable { private String id ; private String pre; private String name; private CyclicBarrier barrier; public CaseToTestRail(String name, CyclicBarrier barrier) { this.name = name; this.barrier = barrier; } @Override public void run() { // TODO Auto-generated method stub try { System.out.println(name + "已準備生成TestRail case"); TimeUnit.SECONDS.sleep(1 + (new Random().nextInt(5))); this.id = name; barrier.await(); this.pre = id; TimeUnit.SECONDS.sleep(1 + (new Random().nextInt(3))); System.out.println(pre + "====前提條件"); barrier.await(); System.out.println(pre + "===========後續條件"); } catch (InterruptedException e) { // TODO Auto-generated catch block System.out.println("Inter e"); e.printStackTrace(); } catch (BrokenBarrierException e) { // TODO Auto-generated catch block System.out.println("BrokenBarrierException"); e.printStackTrace(); } } }
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String> list = new ArrayList<String>();
for (int i = 1; i <= 5; i++) {
list.add("case" + i);
}
ExecutorService pool = Executors.newFixedThreadPool(list.size());
List<Runnable> runnalbes = new ArrayList<Runnable>();
CyclicBarrier barrier = new CyclicBarrier(list.size());
for (int i = 0; i < list.size(); i++) {
final String caseName = list.get(i);
CaseToTestRail runnables = new CaseToTestRail(caseName, barrier);
runnalbes.add(runnables);
pool.execute(runnables);
}
System.out.println("下一個task。。");
}
}