【十二】Java多线程J.U.C之 CyclicBarrier

版权声明:转载注明出处 https://blog.csdn.net/jy02268879/article/details/86010106

CyclicBarrier是一个同步工具类,它允许一组线程互相等待,直到到达某个公共屏障点。

与CountDownLatch不同的是该barrier在释放等待线程后可以重用,所以称它为循环(Cyclic)的屏障(Barrier)。

CyclicBarrier支持一个可选的Runnable命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。

代码示例

package com.sid.thread.CyclicBarrierTest;

import java.util.Date;
import java.util.concurrent.CyclicBarrier;

/**
 * @program: thread-test
 * @description:       让多个线程互相等待某一事件的发生,然后同时被唤醒。
 *                      CyclicBarrier可以译为循环屏障,也有类似的功能。
 *                      CyclicBarrier可以在构造时指定需要在屏障前执行await的个数,所有对await的调用都会等待
 *                      示例:有五个线程都调用barrier.await()了之后,该五个线程一起唤醒
 * @author: Sid
 * @date: 2018-11-27 14:34
 * @since: 1.0
 **/
public class CyclicBarrierDemo {
    public static void main(String[] args) {
        int totalThread = 5;
        /**
         * CyclicBarrier可以在构造时指定需要在屏障前执行await的个数,所有对await的调用都会等待
         */
        CyclicBarrier barrier = new CyclicBarrier(totalThread,new Runnable() {
            public void run() {
                System.out.println(String.format("%s\t%s %s", new Date(), Thread.currentThread().getName(), " merge runnable"));
            }});


        for(int i = 0; i < totalThread; i++) {
            new Thread(() -> {
                System.out.println(String.format("%s\t%s %s", new Date(), Thread.currentThread().getName(), " is waiting"));
                try {
                    /**
                     * await() 等待其它参与方的到来(调用await())。
                     * 如果当前调用是最后一个await,则唤醒所有其它的线程的等待,
                     * 并且如果在构造CyclicBarrier时指定了action,当前线程会去执行该action,
                     * 然后该方法返回该线程调用await的次序(getParties()-1说明该线程是第一个调用await的,0说明该线程是最后一个执行await的),
                     * 接着该线程继续执行await后的代码。
                     * 如果该调用不是最后一个调用,则阻塞等待;
                     * 如果等待过程中,当前线程被中断,
                     * 则抛出InterruptedException;
                     * 如果等待过程中,其它等待的线程被中断,或者其它线程等待超时,
                     * 或者该barrier被reset,或者当前线程在执行barrier构造时注册的action时因为抛出异常而失败,
                     * 则抛出BrokenBarrierException。
                     *
                     * await(long timeout, TimeUnit unit) 与await()唯一的不同点在于设置了等待超时时间,等待超时时会抛出TimeoutException。
                     *
                     * reset() 该方法会将该barrier重置为它的初始状态,并使得所有对该barrier的await调用抛出BrokenBarrierException。
                     * */
                    int await = barrier.await();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                System.out.println(String.format("%s\t%s %s", new Date(), Thread.currentThread().getName(), "ended"));
            }).start();
        }
    }
}

运行结果

这里可以看到,最后抵达屏障的线程执行了CyclicBarrier初始化时的Runnable命令。

猜你喜欢

转载自blog.csdn.net/jy02268879/article/details/86010106