該類主要實現了:讓一個線程等待其餘線程完成後再執行的功能,比如Thread.join()
。java
該類的初始化須要一個整數值count,當每次調用CountDownLatch.countDown()
時Count會遞減。直到count降到0時,全部執行CountDownLatch.await()
的方法都會返回。算法
初始化了一個共享變量latch,並賦予count爲3數據庫
CountDownLatch latch = new CountDownLatch(3);
建立一個任務,睡眠1秒僞裝執行任務,最後執行countDownide
@Override public void run() throw InterruptedException{ System.out.println("執行任務..."); Thread.sleep(1000); latch.countDown(); }
主線程裏執行以下方法工具
// 調用3個線程執行上述的任務 ... latch.await(); System.out.println("執行結束")
當三個任務線程所有執行完latch.countDown()時,main線程就會從阻塞的await()中返回,最後輸出"執行結束"。
注意:CountDownLatch 只能使用一次,下一次使用要從新建立一個。學習
該類和CountDownLatch有點相似,不過從名字就能夠看出它是一個可循環使用 的類。它的功能主要是等待全部線程達到某個位置,而後統一執行。能夠想象成出發旅遊,你們都先到集合地等待,待全部人都到了,就能夠出發了。線程
建立一個屏障code
CyclicBarrier barrier = new CyclicBarrier(4);
任務類,讓先完成的任務進行等待,等待其餘線程到達get
@Override public void run() throw InterruptedException{ System.out.println(Thread.currentThread.getName() + " -> 到達集合點"); barrier.await(); System.out.println(Thread.currentThread.getName() + "出發!") }
睡5秒,不讓主線程過早結束同步
// 建立4個線程執行上述的任務 ... Thread.sleep(5000); System.out.println("執行結束")
注意,若是barrier在等待過程當中某個線程被中斷了一次,那麼整個barrier就須要從新來過。
Thread thread = new Thread(() -> { try { barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }); thread.start(); thread.interrupt(); try{ barrier.await(); }catch (Exception e){ System.out.println("沒法等待..."); }
當另起的線程被中斷後,後續的barrier就沒法使用了,會拋出BrokenBarrierException
該類被稱做信號量,用於控制同一時間的線程執行數。想象下面一副場景:
----------------- 🚌 🚌 🚌 🚌↘--------------- 🚌 🚌 🚌 🚌🚌 🚌🚌 🚌 🚌 🚌↗--------------- -----------------
在窄路口裏每次只能經過5輛車,5輛車經過後,後5輛車才能經過。Semaphore的做用就和它很相似,當有20條線程在執行IO密集型的任務,執行完後須要將處理結果存儲到數據庫中。若是數據庫鏈接只有10條,那就要用semaphore去控制拿到數據庫鏈接的線程數量。
Semaphore裏沒用過的方法:
該類是一個用於線程間協做的工具類。Exchanger用於進行線程間的數據交換。它提供一個同步點,在這個通不見,兩個線程能夠交換彼此間的數據。這兩個線程經過exchange方法交換數據:若是第一個線程執行exchange(),它會一直等待第二個線程exchange(),當兩個線程達到同步點,這兩個線程就能夠交換線程。
雖然我不知道這個類有啥做用(ε=ε=ε=┏(゜ロ゜;)┛
可是書上說能夠用於遺傳算法、校對工做:
Exchanger<String> exchanger = new Exchanger<>(); new Thread(() -> { String dataOfAThread = Thread.currentThread().getName() + "-----A的數據"; try { String resultOfBThread = exchanger.exchange(dataOfAThread); System.out.println(Thread.currentThread().getName() + "-------> " + resultOfBThread); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); new Thread(() -> { String dataOfBThread = Thread.currentThread().getName() + "-----B的數據"; try { String resultOfAThread = exchanger.exchange(dataOfBThread); System.out.println(Thread.currentThread().getName() + "-------> " + resultOfAThread); } catch (InterruptedException e) { e.printStackTrace(); } }).start();
最後輸出:
Thread-1-------> Thread-0-----A的數據 Thread-0-------> Thread-1-----B的數據
從新熟悉一下同步工具,學習到了CyclicBarrier被中斷一次後,整個做廢的點;學習到了Exchanger的適用場景