Java随笔-CyclicBarrier

概述

CyclicBarrier和CountDownLatch简直不要太像,CountDownLatch事件只能触发一次,而CyclicBarrier可以多次循环使用,作用是类似的,都是等所有的线程都执行完,再去执行特定的任务,但CyclicBarrier功能比CountDownLatch强大,CyclicBarrier是一组线程相互等待,发生阻塞,直到最后一个线程执行完,再打开屏障,被阻塞的线程继续执行。

使用

方法解释

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

构造方法,parties:参与等待的线程数,小于1会报IllegalArgumentException。

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

构造方法,parties:参与的线程数,小于1会报IllegalArgumentException;barrierAction:最后需要执行的任务。

    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 void breakBarrier() {
        generation.broken = true;
        count = parties;
        trip.signalAll();
    }

只能在持有锁的时候调用,破坏屏障唤醒所有线程。

    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();   // break the current generation
            nextGeneration(); // start a new generation
        } finally {
            lock.unlock();
        }
    }

重置屏障,回到初始屏障未被破坏的状态。

使用

public class Programmer extends Thread {
    private CyclicBarrier cyclicBarrier;
    private int index;

    public Programmer(CyclicBarrier cyclicBarrier, int index) {
        this.cyclicBarrier = cyclicBarrier;
        this.index = index;
    }

    void work() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("程序员" + index + "活干完了");
    }

    void prepare() {
        System.out.println("程序员" + index + "准备好了");
    }

    @Override
    public void run() {
        try {
            // 准备工作
            prepare();
            cyclicBarrier.await();
            // 干活
            work();
            cyclicBarrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5,()-> System.out.println("下一步"));
        for (int i = 0; i < 5; i++) {
            new Programmer(cyclicBarrier, i).start();
        }
    }
}

结果:

程序员1准备好了
程序员0准备好了
程序员3准备好了
程序员2准备好了
程序员4准备好了
下一步
程序员4活干完了
程序员3活干完了
程序员0活干完了
程序员2活干完了
程序员1活干完了
下一步

5个线程,等5个线程都把同样的工作做完后才进行下一步。但凡5个线程中有一个破坏了规矩,比如:等待超时、唤醒等待线程,所有线程都会被唤醒,cyclicBarrier功能失效。

总结

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值