The Phaser class provides a method that is executed each time the phaser changes the phase. It's the onAdvance() method. It receives two parameters: the number of the current phase and the number of registered participants; it returns a Boolean value, false if the phaser continues its execution, or true if the phaser has finished and has to enter into the termination state.

The default implementation of this method returns true if the number of registered participants is zero, and false otherwise. But you can modify this behavior if you extend the Phaser class and you override this method. Normally, you will be interested in doing this when you have to execute some actions when you advance from one phase to the next one.

In this recipe, you will learn how to control the phase change in a phaser that is implementing your own version of the Phaser class that overrides the onAdvance() method to execute some actions in every phase change. You are going to implement a simulation of an exam, where there will be some students who have to do three exercises. All the students have to finish one exercise before they can proceed with the next one.

1. Create a class named MyPhaser and specify that it extends from the Phaser class, override the onAdvance() method.

package com.packtpub.java7.concurrency.chapter3.recipe6.task;

import java.util.concurrent.Phaser;

/**
* Implements a subclass of the Phaser class. Overrides the onAdvance method to control
* the change of phase
*
*/
public class MyPhaser extends Phaser { /**
* This method is called when the last register thread calls one of the advance methods
* in the actual phase
* @param phase Actual phase
* @param registeredParties Number of registered threads
* @return false to advance the phase, true to finish
*/
@Override
protected boolean onAdvance(int phase, int registeredParties) {
switch (phase) {
case 0:
return studentsArrived();
case 1:
return finishFirstExercise();
case 2:
return finishSecondExercise();
case 3:
return finishExam();
default:
return true;
}
} /**
* This method is called in the change from phase 0 to phase 1
* @return false to continue with the execution
*/
private boolean studentsArrived() {
System.out.printf("Phaser: The exam are going to start. The students are ready.\n");
System.out.printf("Phaser: We have %d students.\n",getRegisteredParties());
return false;
} /**
* This method is called in the change from phase 1 to phase 2
* @return false to continue with the execution
*/
private boolean finishFirstExercise() {
System.out.printf("Phaser: All the students has finished the first exercise.\n");
System.out.printf("Phaser: It's turn for the second one.\n");
return false;
} /**
* This method is called in the change form phase 2 to phase 3
* @return false to continue with the execution
*/
private boolean finishSecondExercise() {
System.out.printf("Phaser: All the students has finished the second exercise.\n");
System.out.printf("Phaser: It's turn for the third one.\n");
return false;
} /**
* This method is called in the change from phase 3 to phase 4
* @return true. There are no more phases
*/
private boolean finishExam() {
System.out.printf("Phaser: All the students has finished the exam.\n");
System.out.printf("Phaser: Thank you for your time.\n");
return true;
} }

2. Create a class named Student and specify that it implements the Runnable interface. This class will simulate the students of the exam.

package com.packtpub.java7.concurrency.chapter3.recipe6.task;

import java.util.Date;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit; /**
* This class implements an student in the exam
*
*/
public class Student implements Runnable { /**
* Phaser to control the execution
*/
private Phaser phaser; /**
* Constructor of the class. Initialize its objects
* @param phaser Phaser to control the execution
*/
public Student(Phaser phaser) {
this.phaser=phaser;
} /**
* Main method of the student. It arrives to the exam and does three exercises. After each
* exercise, it calls the phaser to wait that all the students finishes the same exercise
*/
public void run() {
System.out.printf("%s: Has arrived to do the exam. %s\n",Thread.currentThread().getName(),new Date());
phaser.arriveAndAwaitAdvance();
System.out.printf("%s: Is going to do the first exercise. %s\n",Thread.currentThread().getName(),new Date());
doExercise1();
System.out.printf("%s: Has done the first exercise. %s\n",Thread.currentThread().getName(),new Date());
phaser.arriveAndAwaitAdvance();
System.out.printf("%s: Is going to do the second exercise. %s\n",Thread.currentThread().getName(),new Date());
doExercise2();
System.out.printf("%s: Has done the second exercise. %s\n",Thread.currentThread().getName(),new Date());
phaser.arriveAndAwaitAdvance();
System.out.printf("%s: Is going to do the third exercise. %s\n",Thread.currentThread().getName(),new Date());
doExercise3();
System.out.printf("%s: Has finished the exam. %s\n",Thread.currentThread().getName(),new Date());
phaser.arriveAndAwaitAdvance();
} /**
* Does an exercise is to wait a random time
*/
private void doExercise1() {
try {
Long duration=(long)(Math.random()*10);
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
} /**
* Does an exercise is wait a random time
*/
private void doExercise2() {
try {
Long duration=(long)(Math.random()*10);
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
} /**
* Does an exercise is wait a random time
*/
private void doExercise3() {
try {
Long duration=(long)(Math.random()*10);
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

3. Implement the main class of the example by creating a class named Main.

package com.packtpub.java7.concurrency.chapter3.recipe6.core;

import com.packtpub.java7.concurrency.chapter3.recipe6.task.MyPhaser;
import com.packtpub.java7.concurrency.chapter3.recipe6.task.Student; /**
* Main class of the example
*
*/
public class Main { /**
* Main method of the example
* @param args
*/
public static void main(String[] args) { // Creates the Phaser
MyPhaser phaser=new MyPhaser(); // Creates 5 students and register them in the phaser
Student students[]=new Student[5];
for (int i=0; i<students.length; i++){
students[i]=new Student(phaser);
phaser.register();
} // Create 5 threads for the students and start them
Thread threads[]=new Thread[students.length];
for (int i=0; i<students.length; i++) {
threads[i]=new Thread(students[i],"Student "+i);
threads[i].start();
} // Wait for the finalization of the threads
for (int i=0; i<threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} // Check that the Phaser is in the Terminated state
System.out.printf("Main: The phaser has finished: %s.\n",phaser.isTerminated()); } }

This exercise simulates the realization of an exam that has three exercises. All the students have to finish one exercise before they can start the next one. To implement this synchronization requirement, we use the Phaser class, but you have implemented your own phaser extending the original class to override the onAdvance() method.

This method is called by the phaser before making a phase change and before waking up all the threads that were sleeping in the arriveAndAwaitAdvance() method. This method receives as parameters the number of the actual phase, where 0 is the number of the first phase and the number of registered participants. The most useful parameter is the actual phase. If you execute a different operation depending on the actual phase, you have to use an alternative structure (if/else or switch) to select the operation you want to execute. In the example, we used a switch structure to select a different method for each change of phase.

The onAdvance() method returns a Boolean value that indicates if the phaser has terminated or not. If the phaser returns a false value, it indicates that it hasn't terminated, so the threads will continue with the execution of other phases. If the phaser returns a true value, then the phaser still wakes up the pending threads, but moves the phaser to the terminated state, so all the future calls to any method of the phaser will return immediately, and the isTerminated() method returns the true value.

In the Core class, when you created the MyPhaser object, you didn't specify the number of participants in the phaser. You made a call to the register() method for every Student object created to register a participant in the phaser. This calling doesn't establish a relation between the Student object or the thread that executes it and the phaser. Really, the number of participants in a phaser is only a number. There is no relationship between the phaser and the participants.

Java Concurrency - Phaser, Controlling phase change in concurrent phased tasks的更多相关文章

  1. Java Concurrency - 浅析 Phaser 的用法

    One of the most complex and powerful functionalities offered by the Java concurrency API is the abil ...

  2. Java Concurrency - ScheduledThreadPoolExecutor

    The Executor framework provides the ThreadPoolExecutor class to execute Callable and Runnable tasks ...

  3. Java线程--Phaser使用

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11867895.html Java线程--Phaser使用, 代码里头有详细注释: packag ...

  4. Java Concurrency - 浅析 CyclicBarrier 的用法

    The Java concurrency API provides a synchronizing utility that allows the synchronization of two or ...

  5. Java Concurrency - 线程执行器

    Usually, when you develop a simple, concurrent-programming application in Java, you create some Runn ...

  6. Java Concurrency - Callable & Future

    One of the advantages of the Executor framework is that you can run concurrent tasks that return a r ...

  7. 《Java Concurrency》读书笔记,使用JDK并发包构建程序

    1. java.util.concurrent概述 JDK5.0以后的版本都引入了高级并发特性,大多数的特性在java.util.concurrent包中,是专门用于多线并发编程的,充分利用了现代多处 ...

  8. 《深入浅出 Java Concurrency》——原子操作

    part1 从AtomicInteger開始 从相对简单的Atomic入手(java.util.concurrent是基于Queue的并发包.而Queue.非常多情况下使用到了Atomic操作.因此首 ...

  9. 深入浅出 Java Concurrency (35): 线程池 part 8 线程池的实现及原理 (3)[转]

    线程池任务执行结果 这一节来探讨下线程池中任务执行的结果以及如何阻塞线程.取消任务等等. 1 package info.imxylz.study.concurrency.future;2 3 publ ...

随机推荐

  1. CodeForces 706B Interesting drink (二分查找)

    题意:给定 n 个数,然后有 m 个询问,每个询问一个数,问你小于等于这个数的数有多少个. 析:其实很简单么,先排序,然后十分查找,so easy. 代码如下: #pragma comment(lin ...

  2. PHP- Windows无法在本地计算机启动Apache的解决方法

    装好了WAMP,开始可以进行我的PHP学习了.可是装后却打不开locahost. 百度后如下解决了:"Windows不能在本地计算机启动Apache2.有关更多信息,查阅系统事件日志.如果这 ...

  3. ASMB的BUG(ORA-04030 kfmditer)导致数据库宕机

    ASMB的BUG(ORA-04030 kfmditer)导致数据库宕机 现象: 客户的一个重要生产系统RAC的一个实例宕机,查看alert日志: Fri Jun 21 17:05:52 2013 Er ...

  4. 《UNIX环境高级编程》笔记--更改用户ID和组ID

    在unix系统中,特权是基于用户和组ID的,当程序需要增加特权,或需要访问当前并不允许访问的资源时,我们需要更换自己 用户ID或组ID,使的新ID具有合适的特权或访问权限.与此类似,当程序需要降低其特 ...

  5. java.io.File类

    java.io.File类 1.凡是与输入.输出相关的类.接口等都定义在java.io包下 2.File是一个类.能够有构造器创建其对象.此对象相应着一个文件(.txt .avi .doc .ppt ...

  6. Codeforces Gym 100002 B Bricks 枚举角度

    Problem B Bricks" Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100002 ...

  7. .Net语言 APP开发平台——Smobiler学习日志:开发APP时,如何快速地实现屏幕自适应

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.属性介绍 设置控件在客户端屏幕可见并超出客户端屏幕时,是否自动调节高度以适应屏幕高 ...

  8. Delphi调用Dll的的2种写法

         unit Unit1;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, F ...

  9. C++中的inline函数

    内联函数: () 内联函数定义和作用: 将一个函数声明为inline,那么函数就成为内联函数.内联函数通常就是它在程序中每个调用点上“内联地”展开.从定义上看,内联函数跟一般函数不一样,一般函数调用的 ...

  10. show engine innodb status解读

    xiaoboluo768   注:以下内容为根据<高性能mysql第三版>和<mysql技术内幕innodb存储引擎>的innodb status部分的个人理解,如果有错误,还 ...