【Java并发编程实战】—–“J.U.C”:Phaser
来源:互联网 发布:合肥行知 编辑:程序博客网 时间:2024/06/06 05:53
CyclicBarrier,允许一组线程互相等待,直到到达某个公共屏障点。它提供的await()可以实现让所有参与者在临界点到来之前一直处于等待状态。
CountDownLatch,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。它提供了await()、countDown()两个方法来进行操作。
在Phaser中,它把多个线程协作执行的任务划分为多个阶段,编程时需要明确各个阶段的任务,每个阶段都可以有任意个参与者,线程都可以随时注册并参与到某个阶段。
构造
Phaser创建后,初始阶段编号为0,构造函数中指定初始参与个数。
注册:Registration
Phaser支持通过register()和bulkRegister(int parties)方法来动态调整注册任务的数量。
Arrival
每个Phaser实例都会维护一个phase number,初始值为0。每当所有注册的任务都到达Phaser时,phase number累加,并在超过Integer.MAX_VALUE后清零。arrive()和arriveAndDeregister()方法用于记录到达;其中arrive(),某个参与者完成任务后调用;arriveAndDeregister(),任务完成,取消自己的注册。arriveAndAwaitAdvance(),自己完成等待其他参与者完成,进入阻塞,直到Phaser成功进入下个阶段。
example 1
- public class PhaserTest_1 {
- public static void main(String[] args) {
- Phaser phaser = new Phaser(5);
- for(int i = 0 ; i < 5 ; i++){
- Task_01 task_01 = new Task_01(phaser);
- Thread thread = new Thread(task_01, "PhaseTest_" + i);
- thread.start();
- }
- }
- static class Task_01 implements Runnable{
- private final Phaser phaser;
- public Task_01(Phaser phaser){
- this.phaser = phaser;
- }
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "执行任务完成,等待其他任务执行......");
- //等待其他任务执行完成
- phaser.arriveAndAwaitAdvance();
- System.out.println(Thread.currentThread().getName() + "继续执行任务...");
- }
- }
- }
运行结果:
PhaseTest_0执行任务完成,等待其他任务执行......PhaseTest_1执行任务完成,等待其他任务执行......PhaseTest_3执行任务完成,等待其他任务执行......PhaseTest_2执行任务完成,等待其他任务执行......PhaseTest_4执行任务完成,等待其他任务执行......PhaseTest_4继续执行任务...PhaseTest_1继续执行任务...PhaseTest_0继续执行任务...PhaseTest_2继续执行任务...PhaseTest_3继续执行任务...
在该实例中我们可以确认,所有子线程的****+”继续执行任务…”,都是在线程调用arriveAndAwaitAdvance()方法之后执行的。
example 2
前面提到过,Phaser提供了比CountDownLatch、CyclicBarrier更加强大、灵活的功能,从某种程度上来说,Phaser可以替换他们:
- public class PhaserTest_5 {
- public static void main(String[] args) {
- Phaser phaser = new Phaser(1); //相当于CountDownLatch(1)
- //五个子任务
- for(int i = 0 ; i < 3 ; i++){
- Task_05 task = new Task_05(phaser);
- Thread thread = new Thread(task,"PhaseTest_" + i);
- thread.start();
- }
- try {
- //等待3秒
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- phaser.arrive(); //countDownLatch.countDown()
- }
- static class Task_05 implements Runnable{
- private final Phaser phaser;
- Task_05(Phaser phaser){
- this.phaser = phaser;
- }
- @Override
- public void run() {
- phaser.awaitAdvance(phaser.getPhase()); //countDownLatch.await()
- System.out.println(Thread.currentThread().getName() + "执行任务...");
- }
- }
- }
在这里,任务一开始并没有真正执行,而是等待三秒后执行。
对于CyclicBarrier就更加简单了,直接arriveAndAwaitAdvance()方法替换,如example 1。
example 3
在CyclicBarrier中当任务执行完之后可以执行一个action,在Phaser中同样有一个对应的action,只不过Phaser需要重写onAdvance()方法:
- public class PhaserTest_3 {
- public static void main(String[] args) {
- Phaser phaser = new Phaser(3){
- /**
- * registeredParties:线程注册的数量
- * phase:进入该方法的线程数,
- */
- protected boolean onAdvance(int phase, int registeredParties) {
- System.out.println("执行onAdvance方法.....;phase:" + phase + "registeredParties=" + registeredParties);
- return phase == 3;
- }
- };
- for(int i = 0 ; i < 3 ; i++){
- Task_03 task = new Task_03(phaser);
- Thread thread = new Thread(task,"task_" + i);
- thread.start();
- }
- while(!phaser.isTerminated()){
- phaser.arriveAndAwaitAdvance(); //主线程一直等待
- }
- System.out.println("主线程任务已经结束....");
- }
- static class Task_03 implements Runnable{
- private final Phaser phaser;
- public Task_03(Phaser phaser){
- this.phaser = phaser;
- }
- @Override
- public void run() {
- do{
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(Thread.currentThread().getName() + "开始执行任务...");
- phaser.arriveAndAwaitAdvance();
- }while(!phaser.isTerminated());
- }
- }
- }
运行结果:
task_0开始执行任务...task_1开始执行任务...task_1执行onAdvance方法.....;phase:0registeredParties=3task_2开始执行任务...task_0开始执行任务...task_1开始执行任务...task_0执行onAdvance方法.....;phase:1registeredParties=3task_2开始执行任务...task_2执行onAdvance方法.....;phase:2registeredParties=3主线程任务已经结束....task_0开始执行任务...
参考博文:
1、What’s New on Java 7 Phaser
2、http://blog.csdn.net/andycpp/article/details/8838820
- 【Java并发编程实战】—–“J.U.C”:Phaser
- 【Java并发编程实战】—–“J.U.C”:Phaser
- 【Java并发编程实战】-----“J.U.C”:Phaser
- 【Java并发编程实战】—–“J.U.C”:Condition
- 【Java并发编程实战】—–“J.U.C”:Semaphore
- 【Java并发编程实战】—–“J.U.C”:ReentrantReadWriteLock
- 【Java并发编程实战】—–“J.U.C”:CyclicBarrier
- 【Java并发编程实战】—–“J.U.C”:CountDownlatch
- 【Java并发编程实战】—–“J.U.C”:Condition
- 【Java并发编程实战】—–“J.U.C”:Semaphore
- 【Java并发编程实战】—–“J.U.C”:ReentrantReadWriteLock
- 【Java并发编程实战】—–“J.U.C”:CyclicBarrier
- 【Java并发编程实战】—–“J.U.C”:CountDownlatch
- 【Java并发编程实战】—–“J.U.C”:锁,lock
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之一简介
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之二lock方法分析
- 【Java并发编程实战】—–“J.U.C”:锁,lock
- 【Java并发编程实战】—–“J.U.C”:ReentrantLock之一简介
- webapp应用Servlet
- 创建目录以及文件写入
- CentOS7配置redis开机启动
- 模仿qq截取圆形头像
- zepto获取select元素的选中值的文本以及值的获取
- 【Java并发编程实战】—–“J.U.C”:Phaser
- 算法导论的python实现之插入排序
- cocopods
- Android给服务器发送json数据初体验
- 解决UICollectionView的cell间距与设置不符问题
- android解析服务器传来的xml文件和json文件(一)
- nginx.conf配置文件的基本详解
- 解决jquery版本冲突的有效方法
- .NET中操作SQLite