Phaser是Java7新引入的并发API,我们可以将Phaser的概念看成是一个个的阶段, 每个阶段都需要执行的线程任务,任务执行完毕后就进入下一阶段。这里和CyclicBarrier 和CountDownLatch的概念类似, 实际上也确实可以用Phaser代替CyclicBarrier和CountDownLatch。

Phaser也是通过计数器来控制, 在Phaser中叫parties, 我们在指定了parties之后, Phaser可以根据需要动态增加或减少parties的值。

Phaser常用API介绍:

构造方法: public Phaser() {this(null, 0);}public Phaser(int parties) {this(null, parties);}public Phaser(Phaser parent) {this(parent, 0);}public Phaser(Phaser parent, int parties) {if (parties >>> PARTIES_SHIFT != 0)throw new IllegalArgumentException("Illegal number of parties");int phase = 0;this.parent = parent;if (parent != null) {final Phaser root = parent.root;this.root = root;this.evenQ = root.evenQ;this.oddQ = root.oddQ;if (parties != 0)phase = parent.doRegister(1);}else {this.root = this;this.evenQ = new AtomicReference<QNode>();this.oddQ = new AtomicReference<QNode>();}this.state = (parties == 0) ? (long)EMPTY :((long)phase << PHASE_SHIFT) |((long)parties << PARTIES_SHIFT) |((long)parties);}

从上面可以看出, Pahser是存在上下级关系的树状结构, 如果不指定parent和parties默认为null和0。后面我们再对parent结构进行说明。先看看它常用API和对应的功能。

public int register() //向此移相器添加一个新的未到达方。public int bulkRegister(int parties)  // 将给定数量的新未到达方添加到此移相器。public int arriveAndDeregister() // 到达此移相器并从其注销,而无需等待其他人到达public int arrive()  // 到达此移相器,无需等待其他人到达public int arriveAndAwaitAdvance()  // 到达这个移相器并等待其他人public int awaitAdvance(int phase)  // 等待此移相器的相位从给定的相位值前进,如果当前相位不等于给定的相位值或此移相器终止,则立即返回。public int awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit)  // 等待此移相器的相位从给定的相位值或给定的超时时间过去,InterruptedException如果在等待时中断则抛出,或者如果当前相位不等于给定的相位值或此移相器终止,则立即返回public final int getPhase() // 返回当前阶段号public int getRegisteredParties()  // 返回在此移相器上注册的参与方数量public int getArrivedParties()  // 返回已到达此移相器当前阶段的已注册方的数量public int getUnarrivedParties()  // 返回尚未到达此移相器当前阶段的已注册方的数量。

这里列出了Phaser的部分API和功能说明。 下面我们就看一下这些API的具体用法。

1、Phaser代替CountDownLatch: arrive、awaitAdvance

    public static void main(String[] args) {Phaser phaser = new Phaser(5);for (int i = 0; i < 5; i++) {new Thread(() -> {synchronized (phaser) {System.out.println(Thread.currentThread().getName() + "running");phaser.arrive();}}, "thread" + i).start();}System.out.println(Thread.currentThread().getName() + " wait");phaser.awaitAdvance(phaser.getPhase());System.out.println(Thread.currentThread().getName() + "线程执行完毕");}

这里要注意, arrive方法不是线程安全的,如果不加锁,方法很难结束。

输出结果:

这样无论执行多少次, “ main线程执行完毕 ” 这句话都是最后才输出。 我们可以尝试一下,将phaser.arrive() 的调用时机提前,看看方法的执行结果。

2、用phaser代替CyclicBarrier: arriveAndAwaitAdvance

Phaser phaser = new Phaser(5);for(int i=0; i<5; i++){new Thread(()->{System.out.println("=========" + Thread.currentThread().getName());phaser.arriveAndAwaitAdvance();System.out.println("***" + Thread.currentThread().getName());phaser.arriveAndAwaitAdvance();System.out.println("##########" + Thread.currentThread().getName());}).start();}

输出结果:

3.phaser其他API演示:

public static void main(String[] args) {Phaser phaser = new Phaser(5);for(int i=0; i<5; i++){new Thread(()->{synchronized (phaser){phaser.arrive();System.out.println("phaser.getPhase() = "+phaser.getPhase());System.out.println("phaser.getArrivedParties() = "+phaser.getArrivedParties());System.out.println("phaser.getUnarrivedParties() = "+phaser.getUnarrivedParties());}if(Thread.currentThread().getName().equals("thread4")){try {Thread.sleep(1000);System.out.println("=======phaser.getPhase() = "+phaser.getPhase());phaser.arriveAndDeregister();System.out.println("========phaser.arriveAndDeregister() = "+phaser.getPhase());} catch (InterruptedException e) {e.printStackTrace();}}}, "thread"+i).start();}phaser.bulkRegister(3);}

执行结果:

Java多线程---Phaser相关推荐

  1. java多线程下LongAdder、CountDownLatch、CyclicBarrier、Phaser 的用法

    前言 一文读懂java多线程下常用常考的阻塞方法LongAdder.CountDownLatch.CyclicBarrier.Phaser 包含演示代码 高并发模拟,性能比较实例代码 前言 LongA ...

  2. Java多线程发展简史

    摘自: http://www.raychase.net/698 这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从 ...

  3. [转] Java多线程发展简史

    这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从第一个版本开始,在多线程编程方面的大事件和发展脉络有一个描述,并 ...

  4. Java 多线程 并发编程

    转载自  Java 多线程 并发编程 一.多线程 1.操作系统有两个容易混淆的概念,进程和线程. 进程:一个计算机程序的运行实例,包含了需要执行的指令:有自己的独立地址空间,包含程序内容和数据:不同进 ...

  5. java 多线程 一个博客

    http://blog.csdn.net/a352193394/article/category/2563875 Java多线程之~~~线程安全容器的非阻塞容器 在并发编程中,会经常遇到使用容器.但是 ...

  6. 关于java多线程你需要知道的万字真言

    关于java多线程你需要知道的万字真言 程序?进程?线程 线程 个数设置 状态 create runnable runnig blocking / waiting terminate interrup ...

  7. Java 多线程发展简史

    历史热门文章: 可以和面试官聊半个小时的volatile原理 Java中七个潜在的内存泄露风险,你知道几个? JDK 16新特性一览 啥?用了并行流还更慢了 InnoDB自增原理都搞不清楚,还怎么CR ...

  8. Java多线程和并发问题集

    并发是指什么 并发是程序同时执行多个计算的能力. 这可以通过将计算分布在机器的可用CPU内核上(多核CPU支持)或甚至通过同一网络内的不同机器来实现(后台分布式). 进程和线程有什么区别 进程是操作系 ...

  9. Java多线程系列之J.U.C并发包概述

    J.U.C包简介 J.U.C并发包,即java.util.concurrent包,是JDK的核心工具包,是JDK1.5之后,由 Doug Lea实现并引入. 整个java.util.concurren ...

  10. Java多线程进阶(一)—— J.U.C并发包概述

    本文首发于一世流云专栏: https://segmentfault.com/blog... J.U.C包简介 J.U.C并发包,即java.util.concurrent包,是JDK的核心工具包,是J ...

最新文章

  1. UVa11402 Ahoy, Pirates!
  2. 太神奇了!使用C#实现自动核验健康码:(2)OCR识别
  3. 12个有趣的C语言面试题
  4. HTML跳转为啥会404,为什么网页会出现404 not found?
  5. git学习(二):git config命令
  6. 计算机系统建模_包图
  7. java dh算法_java 非对称加密算法DH实现详解
  8. MATLAB多项式计算
  9. 全国多地打造城市三维实景模型 给城市管理带来新利器
  10. 避免让WPF资源字典变得杂乱臃肿
  11. 【Android多屏适配】动态改变Listview item高度
  12. 《Graph neural networks A review of methods and applications》翻译
  13. 期货如何展期(期货合约展期)
  14. 安卓仿苹果音量调节_Android实现音量调节的方法
  15. 51使用LCD1602液晶显示(复习总结)
  16. 微信小程序国际化语言包实现方式(di18n-translate)
  17. openssl漏洞检查修复
  18. SAAS平台构建-后端方案
  19. 【Latex】算法排版规律(中文排版)
  20. 爬虫踩坑系列——etree.HTML解析异常

热门文章

  1. Sails基础之View层
  2. 一元高次方程c语言实现,c语言实现一元二次方程求解
  3. 生成带微信头像的用户二维码
  4. Python之路【第八篇】:面向对象的程序设计
  5. Weighted Boxes Fusion加权检测框合并
  6. 【Kotlin】FarawayPlayer
  7. 轻松使用中移物联网平台Onenet,MQTT协议快速接入实验,使用Onenet平台MQTT协议开发个人智能设备的解决方案
  8. 如何采用SQL Server身份验证登录
  9. android app整包更新,uniapp热更新和整包更新
  10. Python绘制六边形