请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

CyclicBarrier唤醒线程的时机以及唤醒个数

老师,有个问题,当创建CyclicBarrier时传入了一个runnable,那么在唤醒线程时,是先执行完runnable再去唤醒,还是同时进行?我运行的结果好像是先去执行完runnable再去唤醒。但是唤醒几个呢?您课上讲到的如果CyclicBarrier的计数大小为5,而我们有10个线程,那它会5个一波5个一波。但我运行的结果好像不是这样。例如下面的代码:

public class CyclicBarrierDemo {
    static class Task implements Runnable {
        private int id;
        private CyclicBarrier cyclicBarrier;

        public Task(int id, CyclicBarrier cyclicBarrier) {
            this.id = id;
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            try {
                System.out.println("线程" + id + "开始执行任务...");
                Thread.sleep((long) (Math.random() * 5000));
                System.out.println("线程" + id + "执行完部分任务, 到达集合点, 开始等待其他线程到达");
                cyclicBarrier.await();
                System.out.println("线程" + id + "从集合点出发, 开始执行剩下的任务...");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("人满了, 大家统一出发, 倒计时10秒...");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        for (int i = 0; i < 10; i++) {
            new Thread(new Task(i + 1, cyclicBarrier)).start();
        }
    }
}

它的运行结果总是这样的,10个线程先后抵达“集合点”,第一次打开栅栏发生在10个线程抵达集合点之前(因为栅栏要等待10秒而线程抵达集合点最多要5秒),第一次打开栅栏之后放行一个线程,第二次打开栅栏会放行9个线程。为什么是这种结果呢?

正在回答 回答被采纳积分+3

1回答

提问者 深海的星星15138 2020-05-04 21:10:38

内容太多,可能不方便看。总结一下问题就是,在一次计数完成准备唤醒线程时,如果在传入CyclicBarrier的runnable执行完成之前,就又有线程到达了栅栏位置,这时会怎么办?

1 回复 有任何疑惑可以回复我~
  • 悟空 #1
    CyclicBarrier的runnable是在栅栏打开时执行,由最后一个到达集合点的线程执行,这一点可以用Thread的name来验证。
    你的问题很好,我觉得想回答这个问题,可以通过实验现象来得出结论。
    如果在传入CyclicBarrier的runnable执行完成之前,就又有线程到达了栅栏位置,我的实验现象和你一样。
    我看到的现象是,除了每一批最后一个到达集合点的线程之外,其他的线程会等第二批runnable执行完之后,才会放行。
    回复 有任何疑惑可以回复我~ 2020-05-06 15:26:42
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信