多執行緒之CountDownLatch & CyclicBarrier
阿新 • • 發佈:2018-11-19
CountDownLatch 俗稱閉鎖 建構函式中可以傳遞一個count 非負的整數值的數字,表示計數值,當這個計數值減到為0時,才能繼續執行,比如說計算幾個執行緒執行消耗時間 。CyclicBarrier 俗稱同步屏障,它的建構函式有兩種,其他一個也是傳遞一個非負的整數值,表示幾個執行緒需要達到屏障處,另一個建構函式除了那個非零的整數值,還可以傳遞一個Runnable介面的引數,可以在都達到屏障處後在執行一個Runnable介面的實現。旨在所有的執行緒都達到了一個屏障的時候,再執行後續的操作。已計算執行緒的執行時間來說,我們可以嘗試用CountDownLatch,CyclicBarrier及join來試試看。
public class TestCountDownLatchAndCyclicBarrier { public static void main(String[] args) { CountDownLatch cdl = new CountDownLatch(3); TwoUseDemo ldtest = new TwoUseDemo(cdl); Instant start_0 = Instant.now(); for(int i = 0;i<3;i++){ new Thread(()->ldtest.testCountDownLatch(),"ldtest_"+i).start(); } try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" 耗費時間為>>>>>>>>"+Duration.between(start_0, Instant.now())); Instant start_1 = Instant.now(); CyclicBarrier cb = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+" 耗費時間>>>>>>>>"+Duration.between(start_1, Instant.now())); } }); TwoUseDemo cbtest = new TwoUseDemo(cb); for(int i = 0;i<3;i++){ new Thread(()->cbtest.testCyclicBarrier(),"cbtest_"+i).start(); } TwoUseDemo blankTest = new TwoUseDemo(); Instant start_2 = Instant.now(); List<Thread> threads = new ArrayList<>(); IntStream.range(0, 3).forEach((i)->{ threads.add(new Thread(()->{ blankTest.blank(); },"blank_"+i)); }); threads.stream().forEach((t)->{ t.start(); try { t.join(); } catch (Exception e) { e.printStackTrace(); } }); System.out.println(Thread.currentThread().getName()+" 耗費時間為>>>>>>>>"+Duration.between(start_2, Instant.now())); } } class TwoUseDemo{ private CountDownLatch latch; private CyclicBarrier cb; public TwoUseDemo(){ } public TwoUseDemo(CountDownLatch latch){ this.latch = latch; } public TwoUseDemo(CyclicBarrier cb){ this.cb = cb; } public void testCountDownLatch(){ for(int i = 0;i<6;i++){ if(i%2==0){ System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i); } } latch.countDown(); } public void testCyclicBarrier(){ for(int i = 0;i<6;i++){ if(i%2==0){ System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i); } } try { cb.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } public void blank(){ for(int i = 0;i<6;i++){ if(i%2==0){ System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i); } } } }
控制檯執行結果如下
有點特別的地方是 CyclicBarrier 中的最後執行Runnable的執行緒是從原先屏障處等待的幾個執行緒中選擇了一個來執行。