JUC:7_2三大辅助类:CylicBarrier原理及使用、线程加法计数器

JUC:7_1三大辅助类:CountDownLatch原理及使用、线程减法计数器

什么是CyclicBarrier?

允许一组线程全部等待彼此达到共同屏障点的同步辅助。 循环阻塞在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。 屏障被称为循环 ,因为它可以在等待的线程被释放之后重新使用。
A CyclicBarrier支持一个可选的Runnable命令,每个屏障点运行一次,在派对中的最后一个线程到达之后,但在任何线程释放之前。 在任何一方继续进行之前,此屏障操作对更新共享状态很有用。

通俗的讲: CyclicBarrier,栅栏,等到达到指定个数个等待的线程的时候,一起通过,可以理解为是一个加法计数器。(CyclicBarrier是通过await来计数的,每次await之后,内部通过-1到达0的方式来判断是否触及屏障),

构造方法

CyclicBarrier(int parties)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待它时,它将跳闸,并且当屏障跳闸时不执行预定义的动作。
CyclicBarrier(int parties, Runnable barrierAction)
创建一个新的 CyclicBarrier ,当给定数量的线程(线程)等待时,它将跳闸,当屏障跳闸时执行给定的屏障动作,由最后一个进入屏障的线程执行。

CountDownLatch 和 CyclicBarrier 的区别:

CountDownLatch 指定线程执行完毕,在执行操作
CyclicBarrier 执行达到指定线程数,再执行操作

虽然两者看上去都是倒计时
但是CyclicBarrier是通过await来计数的(每次await之后,内部通过-1到达0的方式来判断是否触及屏障),
await之后,本次线程会被阻塞, 直到计数器到达,才会执行后面逻辑,类似于葫芦娃救爷爷

代码

package juc.Test3;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 加法计数器:栅栏,等到达到指定个数个等待的线程的时候,一起通过
 */
public class CyclicBarrierDemo {

    public static void main(String[] args) {

        String[] childs = new String[]{
                "大娃(红娃):葫芦七子之首,葫芦七兄弟中的老大,身强力壮,有一身巨大无比的力气,能随意改变身体大小,脾气很好,能够肩负起一个大哥应有的责任",
                "二娃(橙娃):橙娃天生拥有一双千里眼和顺风耳,妖怪的一切信息都瞒不住他,并且他的千里眼还能看见隐身中的六娃。聪慧温和、沉着稳重、波澜不惊、坚强无畏、善解人意",
                "三娃(黄娃):铜头铁臂,钢筋铁骨,刀枪不入",
                "四娃(绿娃):在七个葫芦娃当中排行第四。能吸吐熊熊烈火,炉火纯青,刚阳烈焰。火焰威力巨大,能焚烧世间万物,火气旺盛,还能使用霹雳攻击",
                "五娃(青娃):吸水,吐水,口吐闪电产生降雨,弱点:水火不相溶,意气用事",
                "六娃(蓝娃):隐身术,透体术,来无影去无踪,聪明机灵,最善于偷盗和行动",
                "七娃(紫娃):最小,没有大本领,倍受哥哥们的关爱,有宝葫芦,可以吸入魔法、兵器和妖怪"
        };
        CyclicBarrier cyclicBarrier = new CyclicBarrier(childs.length, () -> {
            System.out.println("七个葫芦娃了,可以去救爷爷了!");
        });
        for (int i = 0; i < childs.length; i++) {//i局部变量存在栈,new Thred存在堆
            final int temp = i;//jdk1.8有优化,不加final修饰,也会自动识别为final,但是规范上还是要写
            new Thread(() -> {//Lambda表达式本质是一个类,因此相当于是匿名内部类,无法获取类的局部变量,只能操作全局变量,需要final进行修饰才能获得
//                System.out.println(Thread.currentThread().getName() + i + "落地了。");
                System.out.println(Thread.currentThread().getName() + temp + "的葫芦落地了,是" + childs[temp] + "。");

                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }, "树枝").start();
        }
        /**
         * 成员变量的生命周期更长,
         * 当成员变量中引用了局部变量,那么就需要加final,复制一份到堆内存中,
         * 否则引用的该变量就访问不到了
         *
         * 加final,变量会存在堆中的方法区里,子线程共享进程的堆,所以能读到
         * 否则是存在另一个线程的栈中,不同线程读不到
         *
         *
         * CountDownLatch 和 CyclicBarrier 的区别:
         * 虽然两者看上去都是倒计时
         * 但是CyclicBarrier是通过await来计数的(每次await之后,内部通过-1到达0的方式来判断是否触及屏障),
         * await之后,本次线程会被阻塞,
         * 直到计数器到达,才会执行后面的救爷爷
         */


        /**
         *
         * 输出结果:
         * 树枝1的葫芦落地了,是二娃(橙娃):橙娃天生拥有一双千里眼和顺风耳,妖怪的一切信息都瞒不住他,并且他的千里眼还能看见隐身中的六娃。聪慧温和、沉着稳重、波澜不惊、坚强无畏、善解人意。
         * 树枝0的葫芦落地了,是大娃(红娃):葫芦七子之首,葫芦七兄弟中的老大,身强力壮,有一身巨大无比的力气,能随意改变身体大小,脾气很好,能够肩负起一个大哥应有的责任。
         * 树枝2的葫芦落地了,是三娃(黄娃):铜头铁臂,钢筋铁骨,刀枪不入。
         * 树枝3的葫芦落地了,是四娃(绿娃):在七个葫芦娃当中排行第四。能吸吐熊熊烈火,炉火纯青,刚阳烈焰。火焰威力巨大,能焚烧世间万物,火气旺盛,还能使用霹雳攻击。
         * 树枝6的葫芦落地了,是七娃(紫娃):最小,没有大本领,倍受哥哥们的关爱,有宝葫芦,可以吸入魔法、兵器和妖怪。
         * 树枝4的葫芦落地了,是五娃(青娃):吸水,吐水,口吐闪电产生降雨,弱点:水火不相溶,意气用事。
         * 树枝5的葫芦落地了,是六娃(蓝娃):隐身术,透体术,来无影去无踪,聪明机灵,最善于偷盗和行动。
         * 七个葫芦娃了,可以救爷爷!
         */
    }
}

JUC:7_3三大辅助类:Semaphore信号量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值