CyclicBarrier當計數減小到0時,會喚醒全部阻塞在同一個Condition上的線程,與CountDownLatch不一樣的是全部的線程必須同時被喚醒,就比如釣魚比賽,全部人必須同時開始拋竿同樣。CountDownLatch只要求主線程的動做在其餘依賴的線程執行完以後執行就OKjava
測試代碼:設計模式
package com.jv.parallel.feature; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; /* * 處理同一個動做有多個線程同時執行的場景 */ public class TestCyclicBarrier { public static void main(String[] args) { //1.獲得一個CyclicBarrier實例 CyclicBarrier cb = new CyclicBarrier(4); new Thread(new Fishing(cb),"1").start(); new Thread(new Fishing(cb),"2").start(); new Thread(new Fishing(cb),"3").start(); new Thread(new Fishing(cb),"4").start(); } static class Fishing implements Runnable{ CyclicBarrier cb; public Fishing(CyclicBarrier cb) { this.cb = cb; } @Override public void run() { try { cb.await(); System.out.println("第(" + Thread.currentThread().getName() + ")我的開始釣魚"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } }
原理:app
這裏沒有使用到什麼設計模式,CyclicBarrier.await方法調用CyclicBarrier.dowait方法,每次調用await方法都會使計數器-1,當減小到0時就會喚醒全部的線程ide
public int await() throws InterruptedException, BrokenBarrierException { try { return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen } }
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException { return dowait(true, unit.toNanos(timeout)); }
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException { final ReentrantLock lock = this.lock; lock.lock(); try { final Generation g = generation; if (g.broken) throw new BrokenBarrierException(); if (Thread.interrupted()) { breakBarrier(); throw new InterruptedException(); } int index = --count; if (index == 0) { // tripped boolean ranAction = false; try { final Runnable command = barrierCommand; if (command != null) command.run(); ranAction = true; nextGeneration(); return 0; } finally { if (!ranAction) breakBarrier(); } } // loop until tripped, broken, interrupted, or timed out for (;;) { try { if (!timed) trip.await(); else if (nanos > 0L) nanos = trip.awaitNanos(nanos); } catch (InterruptedException ie) { if (g == generation && ! g.broken) { breakBarrier(); throw ie; } else { // We're about to finish waiting even if we had not // been interrupted, so this interrupt is deemed to // "belong" to subsequent execution. Thread.currentThread().interrupt(); } } if (g.broken) throw new BrokenBarrierException(); if (g != generation) return index; if (timed && nanos <= 0L) { breakBarrier(); throw new TimeoutException(); } } } finally { lock.unlock(); } }
最核心的部分就是oop
每次調用await方法都會使內部的計數器臨時變量-1,當減小到0時,就會調用nextGeneration方法測試
private void nextGeneration() { // signal completion of last generation trip.signalAll(); // set up next generation count = parties; generation = new Generation(); }
在這裏喚醒全部阻塞的線程this
提醒:在聲明CyclicBarrier的時候還能夠傳一個Runnable的實現類,當計數器減小到0時,會執行該實現類線程