1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

多线程之CyclicBarrier

前言

昨天我们分享了多线程里面的一个计数器countDownLatch,它的主要作用是控制线程执行顺序,确保上一个操作完成后,下一个线程才能启动运行,但是某些情况下countDownLatch并不能满足我们的需求,比如执行A线程10次后,我们需要执行B线程,然后再执行A线程10次,循环往复,为了应付这样的应用场景,jdk也为我们提供了相应的解决方案——另一个计数器CyclicBarrier,今天我们就一起来看看吧。

CyclicBarrier

CyclicBarrier中文的意思是循环格栅,循环屏障,循环关卡,循环分界线,我觉得叫循环分界线应该更好理解,因为它起的作用就是分隔。它和countDownLatch一样,也是jdk1.5引入的。它的作用有点像触发器,当达到设定的数值时,我们可以触发一个操作。

这样干巴巴讲,大家可能想不来,那我们先看这样一段示例代码:

public class Example {
    static AtomicInteger count = new AtomicInteger(0);
    public static void main(String[] args) {
        AtomicInteger count2 = new AtomicInteger(0);

        CyclicBarrier cyclicBarrier = new CyclicBarrier(10, () -> {
                System.out.println("多线程循环完成" + count2.getAndIncrement());
            });
        for (int i = 0; i < 100; i++) {
            new Thread(new Task(cyclicBarrier)).start();
        }
    }

    static class Task implements Runnable {
        private final CyclicBarrier cyclicBarrier;

        public Task(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                synchronized (count) {
                    System.out.println(count.getAndIncrement());
                }
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

上面的代码中,我们定义了一个原子整数,初始值为0

我们定义了一个cyclicBarrier,触发值我们设定为10,在触发操作里我们打印提示信息;

我们还定义了一个线程,在线程内部我们对原子整数count加一并打印。

然后我们在main方法中循环启动100个线程,运行上面的代码,结果大致如下:

根据运行结果,我们可以看出来,count每增加10,也就是启动十个线程,会触发CyclicBarrier中我们定义的操作,这个数值也就是我们在CyclicBarrier指定的触发值。

如果我们把触发值设置为5,那应该每隔5次就会打印一次,我们验证下:

事实也确实如此,我想到这里大家应该都清楚CyclicBarrier的用法了吧。

关于CyclicBarrier的构造方法我在多说两句,CyclicBarrier有两种构造方法,但是第二种最常用,也就是我们演示的这种:

入参有两个,一个就是触发次数,一个就是触发操作。

另外还需要注意的是,它的await()方法和countDownLatch的方法是不一样的,在它的await()方法中,有一个--count的操作,也就是每次都会把我们设定的数值减一,直至为零,如果--count0,它就会触发我们的barrierAction

对于它的应用场景,我想大家应该能够想到很多,比如固定条数保存数据,多线程提交保存操作,然后达到固定条数提交数据库保存,当然还有很多其他的应用场景,大家可以结合自己的应用需求,好好想一想。

总结

虽然一开始我拿countDownLatchCyclicBarrier做比较,但是事实上,它们两个不具备任何可比性,而且适用的场景也是不一样的。countDownLatch核心方法是countDownaWait,主要用于控制线程执行顺序;CyclicBarrier主要用于有回调需求的场景,而且它的await方法也不一样,但是它们都很有用。

最后,希望大家多动手实现,多练习,毕竟学习这件事,还是实践出真知,多线程想要学的好,juc下面的类少不了,一起加油吧!

posted @ 2021-07-15 13:33  云中志  阅读(113)  评论(0编辑  收藏  举报