Read CyclicBarrier source code

// 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();
        }
    }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326484448&siteId=291194637
Recommended