java并发之 CyclicBarrier 基本使用和源码解读

CyclicBarrier类是我们平常使用的并发编程的一种。

简单理解:有三个跑道,张三跑了5米等人,李四跑了5米等人,A同学到了5米的时候,这个时候就三个人一起跑了。

个人理解:当我们的线程执行到await方法的时候会停止,而且多个线程调用await方法也会停止,直到调用的次数达到符合要求(new CyclicBarrier(5),5就是要求),各个线程的代码继续往下执行。

 

1:代码的简单实现

public class CyclicBarrierTest {

    static CyclicBarrier barrier = new CyclicBarrier(5,new Complete());

    public static void main(String[] args) {
        for (int i=0;i<5;i++){
            Thread thread = new Thread(new Worker());
            thread.start();
        }
    }
    private static class Complete implements Runnable{
        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + "======>> complete");
                Thread.sleep(2000);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private static class Worker implements Runnable{

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + "------->> init");
                System.out.println(Thread.currentThread().getName() + "------->> first start");
                barrier.await();
                System.out.println(Thread.currentThread().getName() + "------->> first end");
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + "------->> second start");
                barrier.await();
                System.out.println(Thread.currentThread().getName() + "------->> second end");
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

 

运行结果

 

 总结:CyclicBarrier 可以支持重复调用await方法,当调用的时候会阻塞当前方法,直到调用次数达到符合的次数,才能继续执行。

当在遇到await方法,会执行相同的步骤,继续等待直到符合才继续执行。

用户也可以定义一个,单独线程。CyclicBarrier 是支持符合规则以后,调用用户自定义个线程。

 

2:CyclicBarrier的源码解析

new CyclicBarrier(个数,线程),构造方法会把两个参数,赋值到parties、count、barrierComand等变量中。

 

 调用await方法,会调用dowait方法。首先会先获取到ReentrantLock这是一个可重入锁,请先了解这个类,这个锁是可以重复获取的。

Generation判断该属性是否为true,不用看。Thread.interrupdated方法也不用,判断是否终止的。

index是调用了count减减的方法,自动减1。

这里面就要区分等于0和不等于0的时候了,然而当第一次调用await的时候是不等于0的,最后一次才是等于0了。

不等于0的时候,会进入一个死循环,判断timed是否为false,意思就是是否为超时获取。当不是超时的时候,会执行trip.await方法。这个方法是Condition类的。如果不了解,请先去了解。功能类似于wait、notify。

当如果大于0的时候,就调用trip.awaitNanos方法。

继续判断Generation.broken该属性是否为true。判断f是否和generation是否相等,可定是不相等的,因为在等于0的时候,会重新给generation赋值。

 

 

 

 

 

 

 

当执行到等于0的时候,会首先执行barrierCommand线程调用run方法,该方法不是start,不会先创建一个线程,是简单的执行run方法。

再去执行nextGeneration方法,该方法会调用trip.singnalAll方法,该方法相当于notifyall一样,对await进行通知。

count会重新赋值一下,就是为什么await能够重复使用的原因。

然后把generation重新赋值一下,感觉就像一个跳出for循环的标识一样。

 

ReentrantLock和Condition类会在后面给大家做详细的介绍。

总结:定义一个可重入锁,调用await方法,如果不等于就调用condition的await等待。如果等于0就调用condition的singleAll方法通知所有线程,该方法会给count重新赋值,重新定义Generation对象,让await等待的跳出for循环。

以上就是个人CyclicBarrier源码的理解,如果有不对的地方,还望大家指点出来,谢谢!

 

posted @ 2020-02-28 16:27  陌然浅笑  阅读(119)  评论(0)    收藏  举报