并发工具-CyclicBarrier源码简析

CyclicBarrier是循环栅栏的意思,循环的等待多个线程执行任务;

<1> 示例代码如下:

public class CyclicBarrierTest {

    public static CyclicBarrier cb = new CyclicBarrier(3, () ->  System.out.println("-------开始点名-------"));

    public static void main(String[] args) {
        System.out.println("三人组团出游,门口等待,准备点名");
        for (int i = 0; i < 3 ; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "到达集合点");
                try { cb.await(); }catch (Exception e){}
                System.out.println(Thread.currentThread().getName() + "到车上");
                try { cb.await(); }catch (Exception e){}
                System.out.println(Thread.currentThread().getName() + "到景区");
                try { cb.await(); }catch (Exception e){}

            }, "线程" + i).start();
        }
    }}

执行结果:

<2>  CyclicBarrier 源码简析:

  • 构造方法
    /**
     * CyclicBarrier JDK1.8分析
     * @param parties 等待的线程个数
     * @param barrierAction 所有等待的线程就绪后要执行任务
     */
    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }
  • await() 方法
/**
     * 每一个线程在某个点等待其他线程,执行await方法
     * @return
     * @throws InterruptedException
     * @throws BrokenBarrierException
     */
    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            //具体的功能方法
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }
  • dowait()栅栏的核心实现
    /**
     * Main barrier code, covering the various policies.
     *
     * 栅栏的核心代码,包含各种条件
     *
     * ReentrantLock lock - CyclicBarrier是用Lock锁实现的,这里用来控制线程的执行
     *
     * CyclicBarrier.Generation 是一个内部类,只是用来进行状态标识
     *
     */
    private int dowait(boolean timed, long nanos)
            throws InterruptedException, BrokenBarrierException,
            TimeoutException {        final ReentrantLock lock = this.lock;
        //每个线程执行await方法获取锁
        lock.lock();
        try {
            //CyclicBarrier在初始化的时候,创建的g赋值给局部变量,在后面使用
            final CyclicBarrier.Generation g = generation;
            //g.broken 默认是false,如果是true表示栅栏出问题了,抛出异常
            if (g.broken)
                throw new BrokenBarrierException();
            //这里判断当前执行await()的线程状态,如果是中断,表明程序出问题了
            if (Thread.interrupted()) {
                //初始化栅栏数据,并将g.broken设置为true
                breakBarrier();
                throw new InterruptedException();
            }
            //count用来记录,还需要几个线程执行await()方法,可以冲破栅栏
            int index = --count;
            //index == 0 表示等待的线程数量够了
            if (index == 0) {  // tripped
                boolean ranAction = false;
                try {
                    final Runnable command = barrierCommand;
                    if (command != null)
                        //执行构造函数里面传进来的任务,这里是由最后一个达到的线程执行的
                        command.run();
                    //表明这次等待任务完成,准备执行下一次栅栏任务
                    ranAction = true;
                    //该方法里用:trip.signalAll(); 唤醒进入方法里的其他线程,重新初始化 count 和 generation
                    //为下一次执行栅栏做准备
                    nextGeneration();
                    return 0;
                } finally {
                    if (!ranAction) breakBarrier();
                }
            }
            // loop until tripped, broken, interrupted, or timed out
            for (;;) {
                try {
                    if (!timed)
                        //执行await()方法获取到锁执行到此,调用condition.await()方法进行挂起,并释放锁,让其他线程获取锁
                        trip.await();
                    else if (nanos > 0L)
                        //同上,区别在于有无等待时间
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    if (g == generation && ! g.broken) {
                        breakBarrier();
                        throw ie;
                    } else {
                        // We‘re about to finish waiting even if we had not
                        // been interrupted, so this interrupt is deemed to
                        // "belong" to subsequent execution.
                        Thread.currentThread().interrupt();
                    }
                }
                if (g.broken)
                    throw new BrokenBarrierException();
                if (g != generation)
                    return index;
                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } finally {
            //释放锁,之前进来的线程,都在调condition.await()方法的时候已经释放锁了,所以这里只有最后一个进来的线程有效果
            lock.unlock();
        }
    }

(笔记整理,待完善)

原文地址:https://www.cnblogs.com/qq-361807535/p/12614623.html

时间: 2024-12-09 02:08:03

并发工具-CyclicBarrier源码简析的相关文章

SpringMVC学习——概念、流程图、源码简析(一)

学习资料:开涛的<跟我学SpringMVC.pdf> 众所周知,springMVC是比较常用的web框架,通常整合spring使用.这里抛开spring,单纯的对springMVC做一下总结. 概念 HandlerMapping:处理器映射,对请求的URL进行映射为具体的处理器(如果有拦截器也包含拦截器,会将Handler和多个HandlerInterceptor封装为HandlerExecutionChain对象) HandlerAdapter:处理器适配器,适配不同类型的处理器,如Cont

JDK源码简析--java.util包中的工具类库

题记 JDK,Java Development Kit. 我们必须先认识到,JDK只是,仅仅是一套Java基础类库而已,是Sun公司开发的基础类库,仅此而已,JDK本身和我们自行书写总结的类库,从技术含量来说,还是在一个层级上,它们都是需要被编译成字节码,在JRE中运行的,JDK编译后的结果就是jre/lib下得rt.jar,我们学习使用它的目的是加深对Java的理解,提高我们的Java编码水平. 本系列所有文章基于的JDK版本都是1.7.16. 本节内容 在本节中,简析java.util包所包

JDK源码简析--java.lang包中的基础类库

题记 JDK,Java Development Kit. 我们必须先认识到,JDK只是,仅仅是一套Java基础类库而已,是Sun公司开发的基础类库,仅此而已,JDK本身和我们自行书写总结的类库,从技术含量来说,还是在一个层级上,它们都是需要被编译成字节码,在JRE中运行的,JDK编译后的结果就是jre/lib下得rt.jar,我们学习使用它的目的是加深对Java的理解,提高我们的Java编码水平. 本系列所有文章基于的JDK版本都是1.7.16. 本节内容 在本节中,简析java.lang包所包

0002 - Spring MVC 拦截器源码简析:拦截器加载与执行

1.概述 Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理.例如通过拦截器可以进行权限验证.记录请求信息的日志.判断用户是否登录等. 2.简单示例 2.1.继承 HandlerInterceptorAdapter 抽象类实现一个拦截器.代码如下: public class DemoInterceptor extends HandlerInterceptorAdapter { @Override    pu

Linux Hugetlbfs内核源码简析-----(一)Hugetlbfs初始化

一.引言 为了实现虚拟内存管理机制,操作系统对内存实行分页管理.自内存“分页机制”提出之始,内存页面的默认大小便被设置为 4096 字节(4KB),虽然原则上内存页面大小是可配置的,但绝大多数的操作系统实现中仍然采用默认的 4KB 页面.当某些应用的需要使用的内存达到几G.甚至几十G的时候,4KB的内存页面将严重制约程序的性能. CPU缓存中有一组缓存专门用于缓存TLB,但其大小是有限的.当采用的默认页面大小为 4KB,其产生的TLB较大,因而将会产生较多 TLB Miss 和缺页中断,从而大大

[tomcat]源码简析 异步/非阻塞和请求构成

提出疑惑 SpringFramework5.0又新增加了一个功能Webflux(响应式编程),是一个典型非阻塞异步的框架.我们知道servlet3.0实现异步(AsyncContext),servlet3.1又提出了非阻塞IO.对此我一直有两点疑惑:1.tomcat8底层已经默认使用NIO了,不是已经是IO非阻塞了吗,怎么又说servlet3.1解决了非阻塞.2.关于异步,如果开发者在serlvet中开一个业务线程来实现,也算异步,为什么3.0还提供了一个组件来解决,那么这种方式和开发者自己开个

第五节:JQuery框架源码简析(1)

(转自老惠的博客) JQuery是一个应用广泛.非常优秀的JavaScript框架,其代码简洁而优雅,有很多值得我们学习的地方.这里仅仅对其代码结构做一个简单的分析,方便大家的理解和学习. 我们进行分析.分解的基准版本是jQuery1.7.1. 开始之前,请准备好以下素材和工具: jQuery源代码:jquery-1.7.1.js 文本编辑器:EditPlus,或者你喜欢的 参考书:<jQuery高级编程>.<jQuery技术内幕:深入解析jQuery架构设计与实现原理>.<

Android -- Camera源码简析,启动流程

com.android.camera.Camera.java,主要的实现Activity,继承于ActivityBase. ActivityBase 在ActivityBase中执行流程: onCreate中进行判断是否是平板: onResume中判断是否锁屏,锁屏&camera不存在时候,mOnResumePending置为true,否则置为false并执行doOnResume: onWindowFocusChanged中判断是否获取到焦点&mOnResumePending,满足的话执行

第五节:JQuery框架源码简析(3)

(续2) 9.DOM 我们将jQuery有关DOM模块的代码放在文件jquery.extend.dom.js中. function jQuery_extend_dom(jQuery){ jQuery.fn.extend({ text: function( text ) { if ( jQuery.isFunction(text) ) { return this.each(function(i) { var self = jQuery( this ); self.text( text.call(t