zoukankan      html  css  js  c++  java
  • 多线程之CyclicBarrier

    前言

    昨天我们分享了多线程里面的一个计数器countDownLatch,它的主要作用是控制线程执行顺序,确保上一个操作完成后,下一个线程才能启动运行,但是某些情况下countDownLatch并不能满足我们的需求,比如执行A线程10次后,我们需要执行B线程,然后再执行A线程10次,循环往复,为了应付这样的应用场景,jdk也为我们提供了相应的解决方案——另一个计数器CyclicBarrier,今天我们就一起来看看吧。

    CyclicBarrier

    CyclicBarrier中文的意思是循环格栅,循环屏障,循环关卡,循环分界线,我觉得叫循环分界线应该更好理解,因为它起的作用就是分隔。它和countDownLatch一样,也是jdk1.5引入的。它的作用有点像触发器,当达到设定的数值时,我们可以触发一个操作。

    这样干巴巴讲,大家可能想不来,那我们先看这样一段示例代码:

    public class Example {
        static AtomicInteger count = new AtomicInteger(0);
        public static void main(String[] args) {
            AtomicInteger count2 = new AtomicInteger(0);
    
            CyclicBarrier cyclicBarrier = new CyclicBarrier(10, () -> {
                    System.out.println("多线程循环完成" + count2.getAndIncrement());
                });
            for (int i = 0; i < 100; i++) {
                new Thread(new Task(cyclicBarrier)).start();
            }
        }
    
        static class Task implements Runnable {
            private final CyclicBarrier cyclicBarrier;
    
            public Task(CyclicBarrier cyclicBarrier) {
                this.cyclicBarrier = cyclicBarrier;
            }
    
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    synchronized (count) {
                        System.out.println(count.getAndIncrement());
                    }
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    上面的代码中,我们定义了一个原子整数,初始值为0

    我们定义了一个cyclicBarrier,触发值我们设定为10,在触发操作里我们打印提示信息;

    我们还定义了一个线程,在线程内部我们对原子整数count加一并打印。

    然后我们在main方法中循环启动100个线程,运行上面的代码,结果大致如下:

    根据运行结果,我们可以看出来,count每增加10,也就是启动十个线程,会触发CyclicBarrier中我们定义的操作,这个数值也就是我们在CyclicBarrier指定的触发值。

    如果我们把触发值设置为5,那应该每隔5次就会打印一次,我们验证下:

    事实也确实如此,我想到这里大家应该都清楚CyclicBarrier的用法了吧。

    关于CyclicBarrier的构造方法我在多说两句,CyclicBarrier有两种构造方法,但是第二种最常用,也就是我们演示的这种:

    入参有两个,一个就是触发次数,一个就是触发操作。

    另外还需要注意的是,它的await()方法和countDownLatch的方法是不一样的,在它的await()方法中,有一个--count的操作,也就是每次都会把我们设定的数值减一,直至为零,如果--count0,它就会触发我们的barrierAction

    对于它的应用场景,我想大家应该能够想到很多,比如固定条数保存数据,多线程提交保存操作,然后达到固定条数提交数据库保存,当然还有很多其他的应用场景,大家可以结合自己的应用需求,好好想一想。

    总结

    虽然一开始我拿countDownLatchCyclicBarrier做比较,但是事实上,它们两个不具备任何可比性,而且适用的场景也是不一样的。countDownLatch核心方法是countDownaWait,主要用于控制线程执行顺序;CyclicBarrier主要用于有回调需求的场景,而且它的await方法也不一样,但是它们都很有用。

    最后,希望大家多动手实现,多练习,毕竟学习这件事,还是实践出真知,多线程想要学的好,juc下面的类少不了,一起加油吧!

  • 相关阅读:
    只用一个字节 计算象棋将帅之间可能的位置
    后缀数组学习
    java 构造不可变类集的使用方法
    topcoder SRM 639 div2
    navicat和pymysql
    表查询
    表的关系对应
    MySQl数据类型和条件限制
    复习之网络编程
    协程
  • 原文地址:https://www.cnblogs.com/caoleiCoding/p/15015073.html
Copyright © 2011-2022 走看看