CountDownLatch和CyclicBarrier 傻傻的分不清?超长精美图文又来了 (6)

CountDownLatch和CyclicBarrier 傻傻的分不清?超长精美图文又来了

上述示例,我们构建 CyclicBarrier 对象时,并没有传递 barrierCommand 对象, 我们修改示例传入一个 barrierCommand 对象,看看会有什么结果:

// 创建 CyclicBarrier 实例,计数器的值设置为2 private static CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> { log.info("全部运行结束"); });

运行结果:

CountDownLatch和CyclicBarrier 傻傻的分不清?超长精美图文又来了

从运行结果中来看,每次冲破屏障后都会执行 CyclicBarrier 初始化 barrierCommand 的方法, 这与我们对 doWait() 方法的分析完全吻合,从上面的运行结果中可以看出,最后一个线程是运行 barrierCommand run() 方法的线程,我们再来形象化的展示一下整个过程

CountDownLatch和CyclicBarrier 傻傻的分不清?超长精美图文又来了

从上图可以看出,barrierAction 与每次突破屏障是串行化的执行过程,假如 barrierAction 是很耗时的汇总操作,那这就是可以优化的点了,我们继续修改代码

// 创建单线程线程池 private static Executor executor = Executors.newSingleThreadExecutor(); // 创建 CyclicBarrier 实例,计数器的值设置为2 private static CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> { executor.execute(() -> gather()); }); private static void gather() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } log.info("全部运行结束"); }

我们这里将 CyclicBarrier 的回调函数 barrierAction使用单线程的线程池,这样最后一个冲破屏障的线程就不用等待 barrierAction 的执行,直接分配个线程池里的线程异步执行,进一步提升效率

运行结果如下:

CountDownLatch和CyclicBarrier 傻傻的分不清?超长精美图文又来了

我们再形象化的看一下整个过程:

CountDownLatch和CyclicBarrier 傻傻的分不清?超长精美图文又来了

这里使用了单一线程池,增加了并行操作,提高了程序运行效率,那问题来了:

如果 barrierAction 非常非常耗时,冲破屏障的任务就可能堆积在单一线程池的等待队列中,就存在 OOM 的风险,那怎么办呢?

这是就要需要一定的限流策略或者使用线程池的拒绝的略等

那把单一线程池换成非单一的固定线程池不就可以了嘛?比如 fixed(5)

乍一看确实能缓解单线程池可能引起的任务堆积问题,上面代码我们看到的 gather() 方法,假如该方法内部没有使用锁或者说存在竟态条件,那 CyclicBarrier 的回调函数 barrierAction 使用多线程必定引起结果的不准确

所以在实际使用中还要结合具体的业务场景不断优化代码,使之更加健壮

总结

本文讲解了 CountDownLatch 和 CyclicBarrier 的经典使用场景以及实现原理,以及在使用过程中可能会遇到的问题,比如将大的 list 拆分作业就可以用到前者,读取多个 Excel 的sheet 页,最后进行结果汇总就可以用到后者 (文中完整示例代码已上传)

最后,再形象化的比喻一下

CountDownLatch 主要用来解决一个线程等待多个线程的场景,可以类比旅游团团长要等待所有游客到齐才能去下一个景点

而 CyclicBarrier 是一组线程之间的相互等待,可以类比几个驴友之间的不离不弃,共同到达某个地方,再继续出发,这样反复

灵魂追问

怎样拿到 CyclicBarrier 的汇总结果呢?

线程池中的 Future 特性你有使用过吗?

接下来,咱们就聊聊那些可以使用的 Future 特性

参考

Java 并发编程实战

Java 并发编程的艺术

Java 并发编程之美


个人博客:https://dayarch.top
加我微信好友, 进群娱乐学习交流,备注「进群」

欢迎持续关注公众号:「日拱一兵」

前沿 Java 技术干货分享

高效工具汇总 | 回复「工具」

面试问题分析与解答

技术资料领取 | 回复「资料」

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwggd.html