// A looping barrier. All threads wait at the barrier for other threads to finish executing. Then execute them individually. // first look at the constructor public CyclicBarrier(int parties) { this(parties, null); } //barrierAction represents the runnable executed after the last thread waiting on the barrier has been executed public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.barrierCommand = barrierAction; } //Wait for other threads to execute here public int await() throws InterruptedException, BrokenBarrierException { try { return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen; } } //If count-1 is not 0, the thread waits on the trip condition. Otherwise wake up the thread waiting on the trip condition. 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 the thread has been interrupted if (Thread.interrupted()) { breakBarrier(); throw new InterruptedException(); } int index = --count; //if all executions have been completed if (index == 0) { // tripped boolean ranAction = false; try { //Execute runnable 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) //wait on trip condition trip.await(); else if (nanos > 0L) nanos = trip.awaitNanos(nanos); } catch (InterruptedException ie) { if (g == generation && ! g.broken) { breakBarrier(); throw ie; } else { 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(); } } //Interrupt this barrier to add all threads waiting on the trip condition to the wake-up queue private void breakBarrier() { generation.broken = true; count = parties; trip.signalAll(); } //Regenerate the next generation CyclicBarrier private void nextGeneration() { //Wake up all threads waiting on trip trip.signalAll(); // set up next generation //Set up next-generation operations (reuse CyclicBarrier) count = parties; generation = new Generation(); } // wait for this time period public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException { return dowait(true, unit.toNanos(timeout)); } // is it damaged public boolean isBroken() { final ReentrantLock lock = this.lock; lock.lock(); try { return generation.broken; } finally { lock.unlock(); } } //Returns the number of participants requested to start this CyclicBarrier. public int getParties() { return parties; } // There are still several participants waiting public int getNumberWaiting() { final ReentrantLock lock = this.lock; lock.lock(); try { return parties - count; } finally { lock.unlock(); } } // Damage the old barrier. Create a new generation public void reset() { final ReentrantLock lock = this.lock; lock.lock(); try { breakBarrier(); // break the current generation nextGeneration(); // start a new generation } finally { lock.unlock(); } }
Read CyclicBarrier source code
Guess you like
Origin http://43.154.161.224:23101/article/api/json?id=326484448&siteId=291194637
Recommended
Ranking