CountDownLatch、CyclicBarrier和Semaphore使用
- 2019 年 10 月 6 日
- 筆記
- CountDownLatch
CountDownLatch是用來執行緒計數的。等待一組執行緒全部執行完後再本執行緒繼續執行。如:A執行緒需要等待B、C和D(由初始化CountDownLatch參數覺得等待多少個執行緒)執行緒執行完後再執行。
主要的方法:
// 構造方法,count決定等待多少個執行緒 public CountDownLatch(int count) // 等待執行緒完成數減1 public void countDown() // 調用await本執行緒會掛起,當等待執行緒未完成數為0,即countDown調用次數等於構造方法參數值時會被喚醒 public void await() public boolean await(long timeout, TimeUnit unit)
以下是CountDownLatch的用法:
public class CountDownLatchTest { public static void main(String[] args) { final CountDownLatch countDownLatch = new CountDownLatch(2); for (int i = 0; i < 2; i++) { new Thread(() -> { try { String name = Thread.currentThread().getName(); System.out.println("子執行緒" + name + "正在運行中......"); TimeUnit.SECONDS.sleep(5); System.out.println("子執行緒" + name + "執行完畢"); countDownLatch.countDown(); } catch (Exception e) { e.printStackTrace(); } }).start(); } try { System.out.println("======等待兩個子執行緒執行完畢"); // 只有子執行緒執行完畢個數等於CountDownLatch初始化個數才會繼續執行await後面程式碼 countDownLatch.await(); System.out.println("兩個子執行緒都執行完畢!!!!!!"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("主執行緒繼續執行中。。。。。。。。"); } }
結果:
子執行緒Thread-0正在運行中...... ======等待兩個子執行緒執行完畢 子執行緒Thread-1正在運行中...... 子執行緒Thread-1執行完畢 子執行緒Thread-0執行完畢 兩個子執行緒都執行完畢!!!!!! 主執行緒繼續執行中。。。。。。。。
- CyclicBarrier
CyclicBarrier 設置一個障礙點,讓同組執行緒到達改點的執行緒等待本組未達到該點的執行緒,同組全部執行緒到達該點才越過障礙物釋放資源,讓其它組循環利用該對象。
主要方法:
// 構造方法設置同組執行緒數 public CyclicBarrier(int parties) // 構造方法設置同組執行緒數;全部達到障礙物時執行barrierAction函數 public CyclicBarrier(int parties, Runnable barrierAction) // 某個執行緒調用await時掛起,需要等同組所有執行緒到達才能喚醒 public int await() throws InterruptedException, BrokenBarrierException
以下是 CyclicBarrier 的用法:
/** * Created on 18/3/15 14:40. * * @author wolf */ public class CyclicBarrierTest { public static void main(String[] args) { int n = 3; CyclicBarrier barrier = new CyclicBarrier(n); for (int i = 0; i < 3; i++) { new Worker(barrier).start(); } try { TimeUnit.SECONDS.sleep(6); System.out.println("--------討厭的循環利用分割線------------"); } catch (Exception e) { e.printStackTrace(); } for (int i = 0; i < n; i++) { new Worker(barrier).start(); } } static class Worker extends Thread { private CyclicBarrier barrier; public Worker(CyclicBarrier barrier) { this.barrier = barrier; } @Override public void run() { long startTime = System.currentTimeMillis(); String name = Thread.currentThread().getName(); System.out.println("執行緒 " + name + " 正在執行任務......."); try { int time = RandomUtils.nextInt(1, 5); TimeUnit.SECONDS.sleep(time); System.out.println("執行緒 " + name + " 執行任務完畢!!!用時:" + time); barrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println("執行緒 " + name + " 全部耗時:"+(System.currentTimeMillis()-startTime)); } } }
- Semaphore
Semaphore 通過名字我們就知道這個計算訊號量,也就是控制獲取資源的許可證。
主要的方法:
// 構造方法設置可用資源的數量,即許可證的數量 public Semaphore(int permits) // 構造方法設置可用資源的數量,即許可證的數量,fair 是否公平獲得許可證,默認是先來後到公平的 public Semaphore(int permits, boolean fair) // 同步獲取許可證, public void acquire() throws InterruptedException // 嘗試獲取許可證,結果直接返回 public boolean tryAcquire() // 嘗試獲取許可證,結果等待時間超時直接返回 public boolean tryAcquire(long timeout, TimeUnit unit) // 釋放許可證,可給其它等待執行緒使用 public void release()
以下是 Semaphore 用法:
public class SemaphoreTest { public static void main(String[] args) { int no = 5; Semaphore semaphore = new Semaphore(2); for (int i = 0; i < no; i++) { new Worker(i, semaphore).start(); } } static class Worker extends Thread { private int no; private Semaphore semaphore; public Worker(int no, Semaphore semaphore) { this.no = no; this.semaphore = semaphore; } @Override public void run() { try { long startTime = System.currentTimeMillis(); semaphore.acquire(); System.out.println("worker " + this.no + " 獲取許可證,開始工作...."); int time = RandomUtils.nextInt(1, 5); TimeUnit.SECONDS.sleep(time); semaphore.release(); System.out.println("worker " + this.no + " 完成工作,釋放許可證!耗時:" + (System.currentTimeMillis() - startTime)); } catch (Exception e) { e.printStackTrace(); } } } }