前面的文章中我们讲到了CyclicBarrier、CountDownLatch的使用,这里再回顾一下CountDownLatch主要用在一个线程等待多个线程执行完毕的情况,而CyclicBarrier用在多个线程互相等待执行完毕的情况。

Phaser是java 7 引入的新的并发API。他引入了新的Phaser的概念,我们可以将其看成一个一个的阶段,每个阶段都有需要执行的线程任务,任务执行完毕就进入下一个阶段。所以Phaser特别适合使用在重复执行或者重用的情况。

基本使用

在CyclicBarrier、CountDownLatch中,我们使用计数器来控制程序的顺序执行,同样的在Phaser中也是通过计数器来控制。在Phaser中计数器叫做parties, 我们可以通过Phaser的构造函数或者register()方法来注册。

通过调用register()方法,我们可以动态的控制phaser的个数。如果我们需要取消注册,则可以调用arriveAndDeregister()方法。

我们看下arrive:

    public int arrive() {return doArrive(ONE_ARRIVAL);}

Phaser中arrive实际上调用了doArrive方法,doArrive接收一个adjust参数,ONE_ARRIVAL表示arrive,ONE_DEREGISTER表示arriveAndDeregister。

Phaser中的arrive()、arriveAndDeregister()方法,这两个方法不会阻塞,但是会返回相应的phase数字,当此phase中最后一个party也arrive以后,phase数字将会增加,即phase进入下一个周期,同时触发(onAdvance)那些阻塞在上一phase的线程。这一点类似于CyclicBarrier的barrier到达机制;更灵活的是,我们可以通过重写onAdvance方法来实现更多的触发行为。

下面看一个基本的使用:

    void runTasks(List<Runnable> tasks) {final Phaser phaser = new Phaser(1); // "1" to register self// create and start threadsfor (final Runnable task : tasks) {phaser.register();new Thread() {public void run() {phaser.arriveAndAwaitAdvance(); // await all creationtask.run();}}.start();}// allow threads to start and deregister selfphaser.arriveAndDeregister();}

上面的例子中,我们在执行每个Runnable之前调用register()来注册, 然后调用arriveAndAwaitAdvance()来等待这一个Phaser周期结束。最后我们调用 phaser.arriveAndDeregister();来取消注册主线程。

下面来详细的分析一下运行步骤:

  1. final Phaser phaser = new Phaser(1);

这一步我们初始化了一个Phaser,并且指定其现在party的个数为1。

  1. phaser.register();

这一步注册Runnable task到phaser,同时将party+1。

  1. phaser.arriveAndAwaitAdvance()

这一步将会等待直到所有的party都arrive。这里只会将步骤2中注册的party标记为arrive,而步骤1中初始化的party一直都没有被arrive。

  1. phaser.arriveAndDeregister();

在主线程中,arrive了步骤1中的party,并且将party的个数减一。

  1. 步骤3中的phaser.arriveAndAwaitAdvance()将会继续执行,因为最后一个phaser在步骤4中arrive了。

多个Phaser周期

Phaser的值是从0到Integer.MAX_VALUE,每个周期过后该值就会加一,如果到达Integer.MAX_VALUE则会继续从0开始。

如果我们执行多个Phaser周期,则可以重写onAdvance方法:

    protected boolean onAdvance(int phase, int registeredParties) {return registeredParties == 0;}

onAdvance将会在最后一个arrive()调用的时候被调用,如果这个时候registeredParties为0的话,该Phaser将会调用isTerminated方法结束该Phaser。

如果要实现多周期的情况,我们可以重写这个方法:

protected boolean onAdvance(int phase, int registeredParties) {return phase >= iterations || registeredParties == 0;}

上面的例子中,如果phase次数超过了指定的iterations次数则就会自动终止。

我们看下实际的例子:

   void startTasks(List<Runnable> tasks, final int iterations) {final Phaser phaser = new Phaser() {protected boolean onAdvance(int phase, int registeredParties) {return phase >= iterations || registeredParties == 0;}};phaser.register();for (final Runnable task : tasks) {phaser.register();new Thread() {public void run() {do {task.run();phaser.arriveAndAwaitAdvance();} while (!phaser.isTerminated());}}.start();}phaser.arriveAndDeregister(); // deregister self, don't wait}

上面的例子将会执行iterations次。

本文的例子请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/Phaser

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

更多内容请访问flydean的博客

Phaser都不懂,还学什么多线程相关推荐

  1. 连八股文都不懂还指望在前端混下去么

    1. HTTP 和 HTTPS 1.http 和 https 的基本概念 http: 是一个客户端和服务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的超文本传输协议. ...

  2. 什么都不懂的学java难不难_零基础转行学java到底难不难

    不少零基础的新手想要转行学习java可是不知道难度,南京学码思下面就给大家详细的说一说转行java的难度,希望能帮助到各位想要了解java的同学. 零基础转行学java到底难不难 新手转行学java到 ...

  3. 连英文都不懂怎么学python_在英语完全不懂的情况下如何学编程?

    有很多人因为英语水平问题而放弃了学习编程 题主你好. 身边不乏有因为完全不懂英语而放弃学习编程,这真的不在少数. 如果说学编程一点都不需要英语那是骗人的,多多少少你还是需要有. 不可否认,编程中用的是 ...

  4. 连英文都不懂怎么学python_不懂英文能学Python吗?

    如今Python作为当下最热门的编程语言之一,也是各大互联网公司急需的人才,薪资也逐年递增,现在乃至未来都是移动互联网时代,如果个人不掌握一门编程语言,估计以后离淘汰也不远了. 深圳python招聘薪 ...

  5. 喂,你连用户模型都不懂还当产品?来,妹纸我手把手教你

    本文以"PMCAFF"为例来逐步说明如何快速建立用户模型. 用户模型目前还没有一个统一的定义,狭义地讲:用户模型是对网站目标群体真实特征的勾勒,是真实用户的虚拟代表.建立用户模型的 ...

  6. element tree不刷新视图_00后都开始找工作了,这些都不懂还聊个啥?

    大家好,我是小跟班! 进来的同学自己找位置坐下, 我要开始给大家科普了. 不知道时候开始, 连95后们都变成了00后眼中的"老年人"... 一声声"叔叔阿姨", ...

  7. 面试官:你连复杂度分析都不懂还敢来面试?

    算法(Algorithm)是指用来操作数据.解决程序问题的一组方法.对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,比如排序就有前面的十大经典排序和几种奇葩排序,虽然结果相同,但在过程中消 ...

  8. 英语一点都不懂怎么学,怎么快速学好英语?

    在教育领域,越来越多的专家学者倡导尽早开始儿童早期英语学习,帮助儿童在最适合的阶段开始习得外语.如果家长现在就开始给孩子学英语,即使不打算双语,也不用担心孩子的学习.如果他们现在开始接触英语,可以大大 ...

  9. 好想学python怎么猜人_好想学英语哦,可是我连那些根本的都不懂.怎么办

    题目: 好想学英语哦,可是我连那些根本的都不懂.怎么办 解答: 很简单.我们学语文的老b师教我们古文时说这就是半门外语,也就是说,学习外语词汇很重要,下面,我给你具体讲讲我.的一些心得.1:在网络上, ...

最新文章

  1. web自动化测试之百度经验-HTTP层面的Web Service自动化测试
  2. gcc生成dll linux,gcc编译dll和调用dll
  3. SAP UI5 setModel of scFld Controller
  4. es6 --- Thunkify源码分析
  5. google annotation笔记
  6. oracle的序列为什么会出错,Oracle系列:(24)序列
  7. java外部工具配置_eclipse配置外部工具利用javah编译生成头文件
  8. 第二十一讲 ASP.NET页面框架
  9. 2010年08期《程序员》配套源码及相关链接
  10. 我国共计34个省级行政区,包括23个省、5个自治区、4个直辖市、2个特别行政区。
  11. input 数字类型
  12. Android保存图片和视频到相册
  13. 中医病案管理、编码、质控、直报、统计系统--正在开发中
  14. 微信小程序显示空格符
  15. 计算机考研英语复试专有名词翻译
  16. Go语言recover
  17. 不用充电的监控摄像头有哪几种供电方式
  18. 区块链常见共识机制简介
  19. python:实现由列表表示的队列算法(附完整源码)
  20. jvarkit包问题反馈:构建成功,部分方法测试失败第4类错误分析

热门文章

  1. string类型比较_redis存json数据时选择string还是hash
  2. BZOJ2806(后缀自动机+DP)
  3. __stdcall和__cdecl的区别
  4. 替换系统wsock32.dll,实现封包拦截
  5. 在类模板的声明和定义中把.h与.cpp分离
  6. MarkdownPad安装以及绘制 UML 图
  7. 混沌系列 | 其实制造“假死”很容易
  8. 当一百万名记者都嚷嚷着“Facebook 很糟糕”......
  9. 【大会】中低端机如何实现复杂多媒体功能?
  10. 6.方法(go语言学习笔记)