• 源码解析-CyclicBarrier


    CyclicBarrier JUC包下 相当于可重复使用的CountDownLauth

    之前聊过 CountDownLauth类似一种栅栏,条件每满足一次 state-1 ,state减到0时 打开栅栏释放所有阻塞住的线程

    CountDownLautch相当于一次性的栅栏,释放过一次后便无用了。而CyclicBarrier 相当于可重复使用的栅栏。

    CountDownLautch是基于AQS实现的,而CyclicBarrier是基于Condition实现的

    基本使用

     new CyclicBarrier( int parties, Runnable barrierAction)  

    第一个参数是栅栏的条件次数,第二个是栅栏准备释放之前执行的操作(由最后一个线程执行)。

    源码分析

    CyclicBarrier几个属性

    Genetation : 静态内部类  代表栅栏一代版本  内部属性broken代表当前版本是否终结

    ReentrantLock : 内部一个锁

    Condition : 用来唤醒线程

    parties : 初始化的栅栏条件数

    Runnable : 栅栏打开之前要执行的操作

    count : 当前计数,每await()一次-1

    1. CyclicBarrier() 构造方法 没啥好说的

    2.await()  每一个线程调用await()时

     dowait() 

     

     

     先上锁

    try{

      获取当前CyclicBarrier版本;

      如果版本已经终结,抛异常;

      if (线程中断) {
        终结当前版本,重置count,唤醒所有线程;

        抛中断异常

      }

      count计数--;

      if (如果计数为0 也就是达到了释放栅栏条件 ){

        执行Runnable中的操作;

        开启下一个CyclicBarrier版本;

        if (如果中途执行Runnable操作失败了报错了){

          最后也一定会 终结当前版本,重置count,唤醒所有线程;

        }

      }

    }

    下边是for循环死循环 

    for ( ; ; ){

      try{

        执行condition.await()方法;

      catch(中断异常){

        如果中途被中断,重置版本,重置count,唤醒所有线程;

      }

      if (版本终结){

        抛异常

      }

      if (获取的版本 已经不是当前版本){

        返回当前计数

      }

      if(等待超时) {
        重置,并抛超时异常;
      }

    finally{ 解锁}

    }

    3.  nextGeneration()  当栅栏达到条件执行此方法   将condition.await()的线程全部唤醒,重置count,换一个新版本

    4.  reset()  更简单了  终结现在的版本,全部重置并开始一个新版本

    什么时候栅栏会被打破,总结如下:

    1. 中断,我们说了,如果某个等待的线程发生了中断,那么会打破栅栏,同时抛出 InterruptedException 异常;
    2. 超时,打破栅栏,同时抛出 TimeoutException 异常;
    3. 指定执行的操作抛出了异常,这个我们前面也说过。
  • 相关阅读:
    二叉树(python3版)
    第九章:树回归
    第八章:线性回归
    第七章:集成学习(利用AdaBoost元算法...)
    第六章:支持向量机(SVM)
    第五章:逻辑回归(Logistic 回归)
    第四章:朴素贝叶斯(bayes)
    win8 webview 无法响应部分页面点击事件
    无法激活Windows应用商店应用程序,"XXXXXXXXX"激活请求失败,错误为"应用未启动".
    无法激活windows应用商店应用程序,应用进程已启动,但激活请求失败,错误为“应用未启动”
  • 原文地址:https://www.cnblogs.com/ttaall/p/13941535.html
Copyright © 2020-2023  润新知