• 关于Java CyclicBarrier reset的理解


    1、在做leetcodeH2O 生成题目时用到了CyclicBarrier,于是尝试写了以下代码:

    1. package utils;
    2. import java.util.concurrent.CyclicBarrier;
    3. import java.util.concurrent.ExecutorService;
    4. import java.util.concurrent.Executors;
    5. import java.util.concurrent.atomic.AtomicInteger;
    6. public class H2O {
    7. private CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {
    8. @Override public void run() {
    9. System.out.println("|");
    10. cb.reset();
    11. }
    12. });
    13. private int count = 5;
    14. public void pintH2O(){
    15. ExecutorService executorService = Executors.newFixedThreadPool(3);
    16. executorService.execute(new Runnable() {
    17. @Override public void run() {
    18. for(int i = 0; i < count; i++){
    19. System.out.print('H');
    20. try{
    21. cb.await();
    22. } catch (Exception e){
    23. System.out.print(" 1error " + e.toString());
    24. }
    25. }
    26. }
    27. });
    28. executorService.execute(new Runnable() {
    29. @Override public void run() {
    30. for(int i = 0; i < count; i++){
    31. System.out.print('H');
    32. try{
    33. cb.await();
    34. } catch (Exception e){
    35. System.out.print(" 2error " + e.toString());
    36. }
    37. }
    38. }
    39. });
    40. executorService.execute(new Runnable() {
    41. @Override public void run() {
    42. for(int i = 0; i < count; i++){
    43. System.out.print('O');
    44. try{
    45. cb.await();
    46. } catch (Exception e){
    47. System.out.print(" 3error " + e.toString());
    48. }
    49. }
    50. }
    51. });
    52. executorService.shutdown();
    53. }
    54. }

    2、执行后产生了如下结果

    1. HHO|
    2. O 1error java.util.concurrent.BrokenBarrierExceptionH 2error java.util.concurrent.BrokenBarrierExceptionH|
    3. H 3error java.util.concurrent.BrokenBarrierExceptionO 1error java.util.concurrent.BrokenBarrierExceptionH|
    4. H 3error java.util.concurrent.BrokenBarrierExceptionO 1error java.util.concurrent.BrokenBarrierExceptionH|
    5. H 2error java.util.concurrent.BrokenBarrierExceptionH 3error java.util.concurrent.BrokenBarrierExceptionO|
    6. 1error java.util.concurrent.BrokenBarrierException 2error java.util.concurrent.BrokenBarrierException
    7. Process finished with exit code 0

    3、在stackoverflow中发现了相同的问题Why CyclicBarrier reset() method is throwing BrokenBarrierException

    原因如下:

    (1)执行reset时,如果有线程正在等待屏障,则此线程会抛出BrokenBarrierException

    (2)CyclicBarrier初始化时配置的Runnable(barrierAction),会在所有线程突破屏障后,由最后一个到达的线程去执行,这就解释了为什么第一次没有线程抛BrokenBarrierException,而后每次都另外2个线程抛出异常

    (3)直观看来,reset做了2件事情:1、突破当前屏障;2、生成一个新屏障

    (4)在查看以下源码后发现:无论是reset还是屏障被突破,都会生成一个新的generation instance,所以在循环中时不必调用reset,一般情况下也用不到此方法,上述代码把reset去掉即可正常执行

    1. public class CyclicBarrier {
    2. /**
    3. * Each use of the barrier is represented as a generation instance.
    4. * The generation changes whenever the barrier is tripped, or
    5. * is reset. There can be many generations associated with threads
    6. * using the barrier - due to the non-deterministic way the lock
    7. * may be allocated to waiting threads - but only one of these
    8. * can be active at a time (the one to which {@code count} applies)
    9. * and all the rest are either broken or tripped.
    10. * There need not be an active generation if there has been a break
    11. * but no subsequent reset.
    12. */
    13. private static class Generation {
    14. boolean broken = false;
    15. }
    16. ....

    参考:

    CyclicBarrier的克星—BrokenBarrierException

  • 相关阅读:
    《AI一键生成抖音商品种草文案》让你秒变带货王!
    Linux JAVA环境的搭建tomcat的部署(含多实例)
    两款宝藏软件安利
    基于SpringBoot+Vue+uniapp的考试系统的详细设计和实现(源码+lw+部署文档+讲解等)
    【Verilog】Verilog基础知识整理
    html模板字符串绑定事件+传递参数
    HTML学生个人网站作业设计——中华美食(HTML+CSS) 美食静态网页制作 WEB前端美食网站设计与实现
    MQ系列5:RocketMQ消息的发送模式
    高速花炮筒纸筒剪切机分切机设计(说明书+CAD图纸)
    图片系列(6)不同版本上 Bitmap 内存分配与回收原理对比
  • 原文地址:https://blog.csdn.net/shengruxiahua2571/article/details/133555647