多线程条件通行工具——CyclicBarrier

CyclicBarrier的作用是,线程进入等待后,需要达到一定数量的等待线程后,再一次性开放通行。

  • CyclicBarrier(int, Runnable)
    构造方法,参数1为通行所需的线程数量,参数2为条件满足时的监听器。
  • int await()/int await(long, TimeUnit)
    线程进入等待,并返回一个进入等待时的倒计索引。
  • int getParties()
    通行所需的线程数量
  • int getNumberWaiting()
    当前线程数量
  • boolean isBroken()
    本批次是否已经终止
  • reset()
    释放本批次通行,并重新接收下一批线程进入。

 

源码分析:

/**
 * @since 1.5
 * @see CountDownLatch
 *
 * @author Doug Lea
 */
public class CyclicBarrier {

    public CyclicBarrier(int parties) {
        this(parties, null);
    }

    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0)
            throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }

    private static class Generation {
        boolean broken = false;
    }

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition trip = lock.newCondition();
    private final int parties;
    private final Runnable barrierCommand;
    private Generation generation = new Generation();

    private int count;

    private void nextGeneration() {
        // 通知本批次所有线程可通行
        trip.signalAll();
        // 重置计数器
        count = parties;
        // 重建批次对象,即不同批次使用不同对象
        generation = new Generation();
    }

    private void breakBarrier() {
        // 标示本批次已终止
        generation.broken = true;
        // 重置计数器
        count = parties;
        // 通知本批次所有线程可通行
        trip.signalAll();
    }

    public int getParties() {
        // 返回通行所需的线程数量
        return parties;
    }

    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe);
        }
    }

    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) {
                // 观察监听器是否正常运行结束
                boolean ranAction = false;
                try {
                    // 执行监听器
                    final Runnable command = barrierCommand;
                    if (command != null)
                        command.run();
                    // 标记正常运行
                    ranAction = true;
                    // 通知所有线程并重置
                    nextGeneration();
                    // 返回索引
                    return 0;
                } finally {
                    // 如果监听器是运行时异常结束,则终止本批次
                    if (!ranAction)
                        breakBarrier();
                }
            }

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

    public boolean isBroken() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 返回本批次是否已经终止
            return generation.broken;
        } finally {
            lock.unlock();
        }
    }

    public void reset() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 终止本批次
            breakBarrier();
            // 开始下一批
            nextGeneration();
        } finally {
            lock.unlock();
        }
    }

    public int getNumberWaiting() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 返回本批次等待中的线程数量
            return parties - count;
        } finally {
            lock.unlock();
        }
    }
}

 

posted @ 2017-01-02 14:56  突破渴望  阅读(183)  评论(0编辑  收藏  举报