CyclicBarrier类

本文详细介绍了Java中的CyclicBarrier类,包括其概念、构造方法、主要操作如await和barrierAction,以及在实际场景中的应用,如线程同步、超时等待和自定义任务执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 CyclicBarrier类的介绍

CyclicBarrier意思是循环屏障,是juc(java.util.concurrent)包下重要的类。在构造CyclicBarrier对象的时候需要传入一组线程的数量值,这组的任一线程到达屏障后就处于阻塞状态,直到这组线程都到达屏障,屏障才会开启,即这组所有的线程才会继续执行线程任务。又因为是循环屏障,所以另一组同样数量的线程也可以使用这个屏障,让这组线程相互等待,等到屏障开启时再继续执行线程任务。

二 CyclicBarrier类的方法

public CyclicBarrier(int parties):创建指定线程数量parties的CyclicBarrier对象,任一线程到达屏障都会阻塞,直到parties个线程到达屏障才会继续执行任务;
public CyclicBarrier(int parties, Runnable barrierAction):创建指定线程数量parties的CyclicBarrier对象,任一线程到达屏障都会阻塞,直到parties个线程到达屏障时,先执行barrierAction线程任务,然后所有的等待线程再继续执行任务;
public int await():线程执行CyclicBarrier对象的await()方法,表示当前线程已经到达屏障,线程处于阻塞状态;
public int await(long timeout, TimeUnit unit):线程执行CyclicBarrier对象的await(timeout)方法,表示当前线程已经到达屏障,线程处于超时阻塞状态:
        如果在超时时间范围内,所有的线程都到达屏障,那么线程正常执行;
        如果超时时间到了,仍然还有线程没有到达屏障,那么线程就会抛出java.util.concurrent.        
        TimeoutException超时异常,然后线程任务继续执行;
public void reset():将屏障重置为其初始状态;
public boolean isBroken():判断屏障是否损坏状态:
        如果线程任务正常执行,屏障规则没有损坏,返回false;
        如果线程任务抛出中断异常,或是超时异常,屏障规则损坏,返回true;
public int getParties():返回开启屏障所需要的线程数量,也即是创建CyclicBarrier对象设置的值;
public int getNumberWaiting():返回正在屏障前等待的线程数量;

三 CyclicBarrier类的使用

3.1 CyclicBarrier类的基本使用

public static void main(String[] args) {
    CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
    new Thread(() -> {
        try {
            System.out.println(Thread.currentThread().getName()
                    + "开始执行任务....");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName()
                    + "完成执行任务....");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }, "线程001").start();
    new Thread(() -> {
        try {
            System.out.println(Thread.currentThread().getName()
                    + "开始执行任务....");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName()
                    + "完成执行任务....");
            TimeUnit.SECONDS.sleep(5);
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName()
                    + "重新完成执行任务....");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }, "线程002").start();
    new Thread(() -> {
        try {
            TimeUnit.SECONDS.sleep(6);
            System.out.println(Thread.currentThread().getName()
                    + "开始执行任务....");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName()
                    + "完成执行任务....");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }, "线程003").start();
    // 线程001开始执行任务....
    // 线程002开始执行任务....
    // 线程002完成执行任务....
    // 线程001完成执行任务....
    // 线程003开始执行任务....
    // 线程003完成执行任务....
    // 线程002重新完成执行任务....
}

创建一个parties为2的CyclicBarrier对象:
        线程001先到达屏障,处于阻塞状态;
        线程002接着到达屏障,和线程001一起满足屏障开启的条件,线程002和线程001接着继续执行代码;
        线程002再次执行CyclicBarrier对象的await()方法,会再次处于阻塞状态,此时是重新使用屏障,在一个线程任务里面可以多次执行CyclicBarrier对象的await()方法;
        线程003接着到达屏障,和线程002一起满足屏障开启的条件,线程003和线程002接着继续执行代码;

3.2 CyclicBarrier类的超时等待

public static void main(String[] args) {
    CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
    DateTimeFormatter formatter =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    new Thread(() -> {
        System.out.println(Thread.currentThread().getName()
                + "开始执行线程任务, 当前时间是 "
                + LocalDateTime.now().format(formatter));
        try {
            cyclicBarrier.await(3, TimeUnit.SECONDS);
            System.out.println(Thread.currentThread().getName()
                    + "超时状态下, try里面的代码不会执行, 当前时间是 "
                    + LocalDateTime.now().format(formatter));
        } catch (InterruptedException | BrokenBarrierException 
                | TimeoutException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()
                + "超时状态下, try外面的代码会执行, 当前时间是 "
                + LocalDateTime.now().format(formatter));
    }, "线程001").start();
    // 线程001开始执行线程任务, 当前时间是 2024-04-18 00:44:02
    // java.util.concurrent.TimeoutException
    // 线程001超时状态下, try外面的代码会执行, 当前时间是 2024-04-18 00:44:05
}

线程001执行超时阻塞方法,在超时时间范围内屏障没有开启,线程001抛出TimeoutException异常,而且try代码块里面的代码不再执行,接着try代码块后面的代码执行

3.3 CyclicBarrier类的barrierAction任务

public static void main(String[] args) {
    CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("所有的线程都已经到达, 请所有线程继续执行...");
    });
    DateTimeFormatter formatter =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    new Thread(() -> {
        System.out.println(Thread.currentThread().getName()
                + "开始执行线程任务, 当前时间是 "
                + LocalDateTime.now().format(formatter));
        try {
            cyclicBarrier.await(3, TimeUnit.SECONDS);
            System.out.println(Thread.currentThread().getName()
                    + "正常状态下, try里面的代码会执行, 当前时间是 "
                    + LocalDateTime.now().format(formatter));
        } catch (InterruptedException | BrokenBarrierException
                | TimeoutException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()
                + "正常状态下, try外面的代码会执行, 当前时间是 "
                + LocalDateTime.now().format(formatter));
    }, "线程001").start();
    new Thread(() -> {
        System.out.println(Thread.currentThread().getName()
                + "开始执行线程任务, 当前时间是 "
                + LocalDateTime.now().format(formatter));

        try {
            cyclicBarrier.await();
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()
                + "执行线程任务完成, 当前时间是 "
                + LocalDateTime.now().format(formatter));
    }, "线程002").start();
    // 线程001开始执行线程任务, 当前时间是 2024-04-18 00:57:37
    // 线程002开始执行线程任务, 当前时间是 2024-04-18 00:57:37
    // 所有的线程都已经到达, 请所有线程继续执行...
    // 线程001正常状态下, try里面的代码会执行, 当前时间是 2024-04-18 00:57:42
    // 线程002执行线程任务完成, 当前时间是 2024-04-18 00:57:42
    // 线程001正常状态下, try外面的代码会执行, 当前时间是 2024-04-18 00:57:42
}

创建一个parties为2的CyclicBarrier对象,线程001和线程002都执行CyclicBarrier对象的await()方法,即到达屏障的线程数量满足屏障开启的条件,先执行构造CyclicBarrier对象时的barrierAction任务,然后是到达屏障的所有线程接着执行线程任务

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值