Phaser es algo similar en funcionalidad de CyclicBarrier y CountDownLatch, pero proporciona más flexibilidad que los dos.
En CyclicBarrier solíamos registrando partes en el constructor, pero Phaser nos brinda la flexibilidad de registrar y eliminar partes en cualquier momento. Para la inscripción de partidos, podemos utilizar cualquiera de los siguientes -
- constructores
- registro, o
- bulkRegister
Para cancelar el registro de partes, podemos utilizar -
Registro- agrega/Registra un nuevo partido unarrived a este sincronizador. Devuelve
- el número de fase de llegada a la que se aplica este registro.
- Si el phaser ha terminado, el valor es negativo y el registro no tiene efecto.
Si la invocación del método onAdvance() está en curso que antes de regresar, este método puede esperar su finalización. Si este phaser tiene un padre, y no hubo partes registradas con este phaser, este phaser hijo también está registrado con su padre.
Programa para demostrar el uso de Phaser>
import java.util.concurrent.Phaser;
public class PhaserTest {
public static void main(String[] args) {
/*Creates a new phaser with 1 registered unArrived parties
* and initial phase number is 0
*/
Phaser phaser=new Phaser(1);
System.out.println("new phaser with 1 registered unArrived parties"
+ " created and initial phase number is 0 ");
//Create 3 threads
Thread thread1=new Thread(new MyRunnable(phaser,"first"),"Thread-1");
Thread thread2=new Thread(new MyRunnable(phaser,"second"),"Thread-2");
Thread thread3=new Thread(new MyRunnable(phaser,"third"),"Thread-3");
System.out.println("\n--------Phaser has started---------------");
//Start 3 threads
thread1.start();
thread2.start();
thread3.start();
//get current phase
int currentPhase=phaser.getPhase();
/*arriveAndAwaitAdvance() will cause thread to wait until current phase
* has been completed i.e. until all registered threads
* call arriveAndAwaitAdvance()
*/
phaser.arriveAndAwaitAdvance();
System.out.println("------Phase-"+currentPhase+" has been COMPLETED----------");
//------NEXT PHASE BEGINS------
currentPhase=phaser.getPhase();
phaser.arriveAndAwaitAdvance();
System.out.println("------Phase-"+currentPhase+" has been COMPLETED----------");
/* current thread Arrives and deRegisters from phaser.
* DeRegistration reduces the number of parties that may
* be required to advance in future phases.
*/
phaser.arriveAndDeregister();
//check whether phaser has been terminated or not.
if(phaser.isTerminated())
System.out.println("\nPhaser has been terminated");
}
}
class MyRunnable implements Runnable{
Phaser phaser;
MyRunnable(Phaser phaser,String name){
this.phaser=phaser;
this.phaser.register(); //Registers/Add a new unArrived party to this phaser.
System.out.println(name +" - New unarrived party has "
+ "been registered with phaser");
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +
" - party has arrived and is working in "
+ "Phase-"+phaser.getPhase());
phaser.arriveAndAwaitAdvance();
//Sleep has been used for formatting output
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//------NEXT PHASE BEGINS------
System.out.println(Thread.currentThread().getName() +
" - party has arrived and is working in "
+ "Phase-"+phaser.getPhase());
phaser.arriveAndAwaitAdvance();
phaser.arriveAndDeregister();
}
}
bulkRegister - añade partes número de nuevos partidos unarrived a este sincronizador. Devuelve
- el número de fase de llegada a la que se aplica este registro.
- Si el phaser ha terminado, el valor es negativo y el registro no tiene efecto.
Si la invocación del método onAdvance() está en curso que antes de regresar, este método puede esperar su finalización.
arriveAndDeregister- Tema actual (Fiesta) Llega y se reinscribe de phaser. La baja en el registro reduce la cantidad de partes que pueden requerirse en el futuro para pasar a la siguiente fase.
Si este phaser tiene un padre, y no hubo partes registradas con este phaser, este phaser hijo también se registra con su padre. Programa para demostrar los padres y el niño Phaser
import java.util.concurrent.Phaser;
public class PhaserParentChildTest {
public static void main(String[] args) {
/*
* Creates a new phaser with no registered unArrived parties.
*/
Phaser parentPhaser = new Phaser();
/*
* Creates a new phaser with the given parent &
* no registered unArrived parties.
*/
Phaser childPhaser = new Phaser(parentPhaser,0);
childPhaser.register();
System.out.println("parentPhaser isTerminated : "+parentPhaser.isTerminated());
System.out.println("childPhaser isTerminated : "+childPhaser.isTerminated());
childPhaser.arriveAndDeregister();
System.out.println("\n--childPhaser has called arriveAndDeregister()-- \n");
System.out.println("parentPhaser isTerminated : "+parentPhaser.isTerminated());
System.out.println("childPhaser isTerminated : "+childPhaser.isTerminated());
}
}
Leer más sobre Phaser en http://www.javamadesoeasy.com/2015/03/phaser-in-java_21.html
The Sun/Oracle [tutoriales] (http://download.oracle.com/javase/tutorial/essential/ concurrency/forkjoin.html) siempre son bastante buenos. – toto2