Java并发编程-移相器
移相器(Phaser)内有2个重要状态,分别是phase和party。
phase就是阶段,初值为0,当所有的线程执行完本轮任务,同时开始下一轮任务时,意味着当前阶段已结束,进入到下一阶段,phase的值自动加1。
party就是线程,party=4就意味着Phaser对象当前管理着4个线程。
Phaser还有一个重要的方法经常需要被重载,那就是boolean onAdvance(int phase, int registeredParties)方法。此方法有2个作用:
1、当每一个阶段执行完毕,此方法会被自动调用,因此,重载此方法写入的代码会在每个阶段执行完毕时执行,相当于CyclicBarrier的barrierAction。
2、当此方法返回true时,意味着Phaser被终止,因此可以巧妙的设置此方法的返回值来终止所有线程。
例如:若此方法返回值为 phase>=3,其含义为当整个线程执行了4个阶段后,程序终止。
Phaser把多个线程执行的任务划分成多个阶段(phase),编程时要明确各个阶段的任务,每个阶段都可以有任意个参与者,线程可以随时注册并参与到某个阶段,当一个阶段中所有线程都成功完成之后,Phaser的onAdvance()被调用,可以通过覆盖添加自定义处理逻辑(类似循环屏障(关卡)使用的Runnable接口),然后Phaser类会自动进入下个阶段。如此循环,直到Phaser不再包含任何参与者。
register(),bulkRegister(),动态添加一个或多个参与者。
arrive(),某个参与者完成任务后调用
arriveAndDeregister(),任务完成,取消自己的注册。
arriveAndAwaitAdvance(),自己完成等待其他参与者完成:进入阻塞,直到Phaser成功进入下个阶段。
awaitAdvance()、awaitAdvanceInterruptibly(),等待phaser进入下个阶段,参数为当前阶段的编号,后者可以设置超时和处理中断请求。
另外,Phaser的一个重要特征是多个Phaser可以组成树形结构,Phaser提供了构造方法来指定当前对象的父对象;当一个子对象参与者>0,会自动注册到父对象中;当=0,自动解除注册。
package org.suxuan; import java.util.concurrent.Phaser;
import java.util.concurrent.atomic.AtomicReferenceArray; public class PhaserDemo {
public static void main(String[] args) {
final int workers = ;
final int workLength = ; final Phaser phaser = new Phaser(workers + );
final AtomicReferenceArray<String> lane1 = new AtomicReferenceArray<String>(new String[workLength]);
final AtomicReferenceArray<String> lane2 = new AtomicReferenceArray<String>(new String[workLength]); new Thread("Producer 1") {
@Override
public void run() {
for (int i = ; i < workLength; i++) {
$sleep(); lane1.set(i, "lane1-answer-" + i); System.out.printf("[%-17s] working in lane1 finished phase [%d]%n",
Thread.currentThread().getName(), phaser.getPhase()); phaser.arriveAndAwaitAdvance();
}
}
}.start(); new Thread("Slower producer 2") {
@Override
public void run() {
for (int i = ; i < workLength; i++) {
$sleep(); lane2.set(i, "lane2-answer-" + i); System.out.printf("[%-17s] working in lane2 finished phase [%d]%n",
Thread.currentThread().getName(), phaser.getPhase()); phaser.arriveAndAwaitAdvance();
}
}
}.start(); new Thread("Slow consumer") {
@Override
public void run() {
for (int start = ; start < workLength; ) {
System.out.printf("[%-17s] about to wait for phase [%d] completion%n",
Thread.currentThread().getName(), start); int phaseInProgress = phaser.awaitAdvance(start); //Read all the way up to the most recent completed phases.
for (int i = start; i < phaseInProgress; i++) {
System.out.printf("[%-17s] read [%s] & [%s] from phase [%d]%n",
Thread.currentThread().getName(), lane1.get(i), lane2.get(i), i);
} start = phaseInProgress; $sleep();
}
}
}.start(); phaser.arriveAndDeregister();
} private static void $sleep(long millis) {
try {
Thread.sleep(millis);
}
catch (InterruptedException e) {
}
}
}
Phaser初始化为3,之后customer线程取消自己的注册(此时只有两个生产者线程间进行同步),awaitAdvance不会阻塞,它直接返回。
两个生产者线程,依次生成结果放置到AtomicReferenceArray中。消费者线程每睡眠80Ms后,从结果集中,把当前已经完成的结果打印出来。
某次运行结果如下:
[Slow consumer ] about to wait for phase [] completion
[Producer ] working in lane1 finished phase []
[Slower producer ] working in lane2 finished phase []
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Producer ] working in lane1 finished phase []
[Slower producer ] working in lane2 finished phase []
[Producer ] working in lane1 finished phase []
[Slow consumer ] about to wait for phase [] completion
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slower producer ] working in lane2 finished phase []
[Producer ] working in lane1 finished phase []
[Slower producer ] working in lane2 finished phase []
[Producer ] working in lane1 finished phase []
[Slower producer ] working in lane2 finished phase []
[Producer ] working in lane1 finished phase []
[Slow consumer ] about to wait for phase [] completion
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slower producer ] working in lane2 finished phase []
[Producer ] working in lane1 finished phase []
[Slower producer ] working in lane2 finished phase []
[Slow consumer ] about to wait for phase [] completion
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slower producer ] working in lane2 finished phase []
[Producer ] working in lane1 finished phase []
[Producer ] working in lane1 finished phase []
[Slower producer ] working in lane2 finished phase []
[Producer ] working in lane1 finished phase []
[Slow consumer ] about to wait for phase [] completion
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
[Slower producer ] working in lane2 finished phase []
[Slow consumer ] about to wait for phase [] completion
[Slow consumer ] read [lane1-answer-] & [lane2-answer-] from phase []
Java并发编程-移相器的更多相关文章
- Java并发编程-总纲
Java 原生支持并发,基本的底层同步包括:synchronized,用来标示一个方法(普通,静态)或者一个块需要同步执行(某一时刻,只允许一个线程在执行代码块).volatile,用来标识一个变量是 ...
- 【Java并发编程实战】----- AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...
- 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport
在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- 【Java并发编程实战】-----“J.U.C”:CLH队列锁
在前面介绍的几篇博客中总是提到CLH队列,在AQS中CLH队列是维护一组线程的严格按照FIFO的队列.他能够确保无饥饿,严格的先来先服务的公平性.下图是CLH队列节点的示意图: 在CLH队列的节点QN ...
- 【Java并发编程实战】-----“J.U.C”:CountDownlatch
上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...
- 【Java并发编程实战】-----“J.U.C”:CyclicBarrier
在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
随机推荐
- 在我朝如何为Brackets安装扩展?
Brackets是Adobe发起的一个开源的HTML编辑器,界面优美简洁.扩展丰富.支持基于Chrome浏览器的实时预览,非常适合对于Web的开发和学习. 但是Brackets的安装包下载和扩展下载, ...
- 【转】Windows Server 2016 安装 IIS 服务时提示指定备用源路径
原文地址:http://www.codingwhy.com/view/973.html 在Windows Serever 2016中安装IIS的时候,遇到以下提示 是否需要指定备用源路径?一个或多个安 ...
- Vue + Bootstrap 制作炫酷个人简历(二)
没想到隔了这么久才来更新. 用vue做简历,不是非常适合,为什么呢. 因为简历没什么数据上的操作,一般都是静态的内容. 不过都说了用Vue来做,也只能强行续命了. 这里是我做好的成品 非一般简历 由 ...
- Nodejs的模块系统
global对象 浏览器端JavaScript中的全局对象为"window",在浏览器中定义的变量都会成为"window"对象的属性. 不像浏览器端JavaSc ...
- centOS7.10 KDE桌面字体设置推荐
安装完centOS7.10的KDE桌面后,第一次使用觉得字体太难看了,特别是终端,看着很难受,调整多次后觉得如下设置舒服很多,分享出来以供参考. 其中等宽字 这样整体看着就会舒服很多 ******** ...
- 【xsy2425】容器 dp
题目大意:有$n$个人,区间大小为$m$,每个人必须覆盖一段区间$[l_i,r_i]$,问你存在多少种不同的覆盖方案,使得区间上每个位置被覆盖的次数不超过$t$. 两种方案被定义为不同当且仅当存在第i ...
- 【sping揭秘】6、IOC容器之统一资源加载策略
Spring中的resource 我们先看看类之间的关系 注意我们的application是间接继承了resourceloader的,也就是说我们的application其实就是一个resourcel ...
- 课程一(Neural Networks and Deep Learning),第一周(Introduction to Deep Learning)—— 0、学习目标
1. Understand the major trends driving the rise of deep learning.2. Be able to explain how deep lear ...
- android app性能优化大汇总(google官方Android性能优化典范 - 第3季)
(1)Fun with ArrayMaps 程序内存的管理是否合理高效对应用的性能有着很大的影响,有的时候对容器的使用不当也会导致内存管理效率低下.Android为移动操作系统特意编写了一些更加高效的 ...
- Android开发之漫漫长途 Ⅶ——Android消息机制(Looper Handler MessageQueue Message)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...