Java多线程之~~~Phaser重写onAdvance方法

在Phaser类中,我们在每个线程中,每个线程进行完一个阶段完成后都会等待其他线程完成后再一起进行,当所

有线程都完成了一个任务的时候,会调用Phaser的onAdvance方法,如果我们想在每个阶段,所有线程都完成他们的阶

段工作后做点啥事的话,那就得继承Phaser类来重写Onadvance这个方法来实现我们的目的,下面我们用一个例子来说

明,例子就是模拟多个学生考试,考试分为三个阶段,每个阶段完成后,都会等待所有的学生完成,同时我们希望在每

一个阶段,所有的学生完成一个阶段的任务后打印出几句话,下面看代码。

package com.bird.concursey.charpet5;

import java.util.Date;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 * This class will simulate the students of the exam
 *
 * @author bird 2014年9月23日 下午8:01:47
 */
public class Student implements Runnable {

	private Phaser phaser;

	public Student(Phaser phaser) {
		super();
		this.phaser = phaser;
	}

	@Override
	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 done the third exercise.%s\n", Thread
				.currentThread().getName(), new Date());
		phaser.arriveAndAwaitAdvance();
	}

	private void doExercise3() {
		try {
			long duration = (long) (Math.random() * 10);
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private void doExercise2() {
		try {
			long duration = (long) (Math.random() * 10);
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private void doExercise1() {
		try {
			long duration = (long) (Math.random() * 10);
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
package com.bird.concursey.charpet5;

import java.util.concurrent.Phaser;

public class MyPhaser extends Phaser {

	@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;
		}
	}

	private boolean finishExam() {
		System.out.printf("Phaser: All the students have finished the exam.\n");
		System.out.printf("Phaser: Thank you for your time.\n");
		return false;
	}

	private boolean finishSecondExercise() {
		System.out
				.printf("Phaser: All the students have finished the second exercise.\n");
		System.out.printf("Phaser: It's time for the third one.\n");
		return false;
	}

	private boolean finishFirstExercise() {
		System.out
				.printf("Phaser: All the students have finished the first exercise.\n");
		System.out.printf("Phaser: It's time for the second one.\n");
		return false;
	}

	/**
	 * It writes two log messages to the console and returns the false value to
	 * indicate that the phaser continues with its execution.
	 *
	 * @return
	 */
	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;
	}

	public static void main(String[] args) {
		MyPhaser phaser = new MyPhaser();
		Student students[] = new Student[5];
		for (int i = 0; i < students.length; i++) {
			students[i] = new Student(phaser);
			phaser.register();
		}

		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();
		}

		for (int i = 0; i < threads.length; i++) {
			try {
				threads[i].join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		System.out.printf("Main: The phaser has finished: %s.\n",phaser.isTerminated());
	}
}

运行结果,

Student 0: Has arrived to do the exam.Tue Sep 23 20:11:50 CST 2014
Student 3: Has arrived to do the exam.Tue Sep 23 20:11:50 CST 2014
Student 2: Has arrived to do the exam.Tue Sep 23 20:11:50 CST 2014
Student 4: Has arrived to do the exam.Tue Sep 23 20:11:50 CST 2014
Student 1: Has arrived to do the exam.Tue Sep 23 20:11:50 CST 2014
Phaser: The exam are going to start. The students are ready.
Phaser: We have 5 students.
Student 1: Is going to do the first exercise.Tue Sep 23 20:11:50 CST 2014
Student 3: Is going to do the first exercise.Tue Sep 23 20:11:50 CST 2014
Student 2: Is going to do the first exercise.Tue Sep 23 20:11:50 CST 2014
Student 4: Is going to do the first exercise.Tue Sep 23 20:11:50 CST 2014
Student 0: Is going to do the first exercise.Tue Sep 23 20:11:50 CST 2014
Student 4: Has done the first exercise.Tue Sep 23 20:11:52 CST 2014
Student 0: Has done the first exercise.Tue Sep 23 20:11:52 CST 2014
Student 1: Has done the first exercise.Tue Sep 23 20:11:52 CST 2014
Student 2: Has done the first exercise.Tue Sep 23 20:11:59 CST 2014

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.

时间: 2024-10-12 21:58:29

Java多线程之~~~Phaser重写onAdvance方法的相关文章

Java多线程实现(四种方法)

1.继承Thread类,重写run方法(其实Thread类本身也实现了Runnable接口) 2.实现Runnable接口,重写run方法 3.实现Callable接口,重写call方法(有返回值) 4.使用线程池(有返回值) 1.继承Thread类,重写run方法 每次创建一个新的线程,都要新建一个Thread子类的对象 启动线程,new Thread子类().start() public class MyThread { public static void main(String ards

java多线程有几种实现方法,都是什么?

转自:http://www.cnblogs.com/liujichang/p/3150387.html 多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 同步的实现方法有两种,分别是synchronized,wait与notify 先看一下java线程运行时各个阶段的运行状态 java实现多线程有两种方法 1.继承Thread类 2.实现Runnable接口 这两种方法的共同点: 不论用哪种方法,都必须用Thread(如果是Thead子类就用它本身)产生线程,然后再调用s

第五周作业(Java多线程创建的三个方法)

我最近在学习Java中多线程,并且觉得多线程这块在以后的Java开发中显得极为重要,就谈一下Java实现多线程的三种方式. JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没有返回值,只有第三种是带返回值的,这种方式一般要求比较高,并且较前两种难一些. 1.继承Thread类实现多线程继承Thread类的本质上也是实现了Runnable接口的一个实

Java多线程之~~~Phaser类实现任务的同步

在多线程开发中,经常会碰到将多个任务分配给多个线程,每个线程执行他的任务,但是,每个任务又分为好几个 阶段,每个阶段期望各个线程同时达到,意思是,每一步每个线程都要同步,当有一个线程走完第一步的时候,他得等 待其他的线程都完成第一步了才能继续下一步,步调一致能解决很多问题.下面我们使用一个例子,这个例子是模拟遍 历机器上的一些文件,找出以log结尾的文件,并且他的最后修改时间为24小时以内,我们开启3个线程去完成这个任 务.并且使用Phaser来同步各个任务. package com.bird.

java多线程有几种实现方法?线程之间如何同步

java中多线程的实现方法有两种:1.直接继承thread类:2.实现runnable接口: 同步的实现方法有五种:1.同步方法:2.同步代码块:3.使用特殊域变量(volatile)实现线程同步:4.使用重入锁实现线程同步:5.使用局部变量实现线程同步 .其中多线程实现过程中需注意重写或者覆盖run()方法,而对于同步的实现方法中使用较常使用的是利用synchronized编写同步方法和代码块.

Java 多线程同步的五种方法

一.引言 闲话不多说,进入正题. 二.为什么要线程同步 因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常.举个例子,如果一个银行账户同时被两个线程操作,一个取100块,一个存钱100块.假设账户原本有0块,如果取钱线程和存钱线程同时发生,会出现什么结果呢?取钱不成功,账户余额是100.取钱成功了,账户余额是0.那到底是哪个呢?很难说清楚.因此多线程同步就是要解决这个问题. 三.不同步时的代码 Bank.java

java多线程的两个创建方法

Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线程,有两种方法: ◆需要从Java.lang.Thread类派生一个新的线程类,重载它的run()方法: ◆实现Runnalbe接口,重载Runnalbe接口中的run()方法. 为什么Java要提供两种方法来创建线程呢?它们都有哪些区别?相比而言,哪一种方法更好呢? 在Java中,类仅支持单继承,

[遇见时光]java多线程中run和start方法

run()方法是方法体,线程里要执行的内容:单独调用时按顺序执行(因为新建的线程还没开启): start()开启一个线程:举个形象的例子就是长跑开始时,每个运动员反应不一样,反应快的就先执行: Java例子: 1 package test; 2 3 public class RunAndStart { 4 public static void main(String[] args) { 5 Runner1 runner1 = new Runner1(); 6 Runner2 runner2 =

Java多线程5:synchronized锁方法块

synchronized同步代码块 用关键字synchronized声明方法在某些情况下是有弊端的,比如A线程调用同步方法执行一个较长时间的任务,那么B线程必须等待比较长的时间.这种情况下可以尝试使用synchronized同步语句块来解决问题.看一下例子: 这个实验可以得出以下两个结论: 1.当A线程访问对象的synchronized代码块的时候,B线程依然可以访问对象方法中其余非synchronized块的部分,第一部分的执行结果证明了这一点 2.当A线程进入对象的synchronized代