CyclicBarrier介绍

2021-10-15 17:44:40 浏览数 (1)

简介

这个类的中文意思是“循环栅栏”。大概的意思就是一个可循环利用的屏障。它的作用就是会让所有线程都等待完成后才会继续下一步行动。CyclicBarrier的计数器更像一个阀门,需要所有线程都到达,然后继续执行,计数器递增,提供reset功能,可以多次使用。

举个例子,就像生活中我们会约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。这里的朋友们就是各个线程,餐厅就是 CyclicBarrier。

代码语言:javascript复制
public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)

parties是参与线程的个数
第二个构造方法有一个Runnable参数,这个参数的意思是最后一个到达线程要做的任务

CyclicBarrier字面意思是“可重复使用的栅栏”,CyclicBarrier 相比 CountDownLatch 来说,要简单很多,其源码没有什么高深的地方,它是 ReentrantLock 和 Condition 的组合使用。

CyclicBarrier 可以有不止一个栅栏,因为它的栅栏(Barrier)可以重复使用(Cyclic)。

代码语言:javascript复制
public int await() throws InterruptedException, BrokenBarrierException
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException

线程调用 await() 表示自己已经到达栅栏
  • CountDownLatch 是一次性的,CyclicBarrier 是可循环利用的。
  • CountDownLatch 参与的线程的职责是不一样的,有的在倒计时,有的在等待倒计时结束。CyclicBarrier 参与的线程职责是一样的。

使用示例

代码语言:javascript复制
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierTest {

    public static void main(String[] args) {
        int threadNum = 5;
        CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {

            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()   " 完成最后任务");
            }
        });

        for(int i = 0; i < threadNum; i  ) {
            new TaskThread(barrier).start();
        }
    }

    static class TaskThread extends Thread {

        CyclicBarrier barrier;

        public TaskThread(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println(getName()   " 到达栅栏 A");
                barrier.await();
                System.out.println(getName()   " 冲破栅栏 A");

                Thread.sleep(2000);
                System.out.println(getName()   " 到达栅栏 B");
                barrier.await();
                System.out.println(getName()   " 冲破栅栏 B");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
执行结果
Thread-3 到达栅栏 A
Thread-4 到达栅栏 A
Thread-0 到达栅栏 A
Thread-2 到达栅栏 A
Thread-1 到达栅栏 A
Thread-0 完成最后任务
Thread-0 冲破栅栏 A
Thread-3 冲破栅栏 A
Thread-4 冲破栅栏 A
Thread-1 冲破栅栏 A
Thread-2 冲破栅栏 A
Thread-1 到达栅栏 B
Thread-2 到达栅栏 B
Thread-4 到达栅栏 B
Thread-0 到达栅栏 B
Thread-3 到达栅栏 B
Thread-3 完成最后任务
Thread-3 冲破栅栏 B
Thread-1 冲破栅栏 B
Thread-2 冲破栅栏 B
Thread-4 冲破栅栏 B
Thread-0 冲破栅栏 B

从打印结果可以看出,所有线程会等待全部线程到达栅栏之后才会继续执行,并且最后到达的线程会完成 Runnable 的任务。

0 人点赞