文档章节

Java并发编程中级篇(六):并发阶段性任务执行阶段切换过程

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/26 19:40
字数 1710
阅读 65
收藏 2

Phaser类提供了一个onAdvance(),这个方法接收两个int类型参数:分别是当前执行阶段数以及注册的参与者数量。方法返回一个布尔值,如果返回false表明Phaser中还有任务在执行,返回true表示这一阶段Phaser执行完毕。

Phaser对象进行阶段切换的时候,在所有在arriveAndAwaitAdvance()方法里休眠线程被唤醒之前,onAdvance()方法将被自动调用。onAdvance()方法返回布尔值表明Phaser终止与否,false表示没有终止,因而县城可以继续执行其他阶段。如果返回true,则Phaser仍然唤醒等待的线程,但是状态已经改变为终止状态,所以继续调用phaser的方法将立即返回,并且isTermination()方法也将返回true。

这个方法的默认实现如下,如果参与者数量是0返回true,否则返回false。但是我们可以通过继承Phaser类类覆盖这个方法。当从一个阶段切换到另一个阶段是需要做一些操作,那么我们就这么做。

protected boolean onAdvance(int phase, int registeredParties) {
  return registeredParties == 0;
}

我们实现一个学生参加考试的例子,需要等待所有学生都到齐后才能参加考试,每个学生都参加三场考试,然后考试结束。

首先我们实现自己的Phaser类MyPhaser,这个类中我们重写onAdvance()方法,并定义每次阶段切换执行的代码。开始打印考试开始参加学生的数量,然后打印第一场考试结束信息,接着打印第二场考试结束信息,最后打印考试结束信息。前三个方法返回false,表明Phaser还在执行,最后一个方法返回true,表明Phaser执行结束。

public class MyPhaser extends Phaser {
    @Override
    protected boolean onAdvance(int phase, int registeredParties) {
        switch (phase) {
            case 0:
                return studentsArrived();
            case 1:
                return finishFirstExercies();
            case 2:
                return finishSecondExercies();
            case 3:
                return finishExam();
            default:
                return true;
        }
    }

    private boolean studentsArrived() {
        System.out.printf("Phaser: The exam are going to start. The %d students are ready.\n",
                getRegisteredParties());
        return false;
    }

    private boolean finishFirstExercies() {
        System.out.printf("Phaser: All the studnets have finished the first exercies.\n");
        return false;
    }

    private boolean finishSecondExercies() {
        System.out.printf("Phaser: All the students have finished the second exercies.\n");
        return false;
    }

    private boolean finishExam() {
        System.out.printf("Phaser: All the students have finished the exam.\n");
        return true;
    }

}

定义Student类,使用phaser模拟四步操作 ,分别是考生到场,第一场考试,第二场考试,第三场考试。

public class Student implements Runnable{
    private Phaser phaser;

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

    @Override
    public void run() {
        System.out.printf("%s: Has arrived to the exam. %s\n", Thread.currentThread().getName(), new Date());
        phaser.arriveAndAwaitAdvance();
        System.out.printf("%s: is going to do the first exercise.\n", Thread.currentThread().getName());
        doExercise1();
        System.out.printf("%s: has done the first exercise.\n", Thread.currentThread().getName());
        phaser.arriveAndAwaitAdvance();
        System.out.printf("%s: is going to do the second exercise.\n", Thread.currentThread().getName());
        doExercise2();
        System.out.printf("%s: has done the second exercise.\n", Thread.currentThread().getName());
        phaser.arriveAndAwaitAdvance();
        System.out.printf("%s: is going to do the third exercise.\n", Thread.currentThread().getName());
        doExercise3();
        System.out.printf("%s: has finished the exam.\n", Thread.currentThread().getName());
        phaser.arriveAndAwaitAdvance();
    }

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

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

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

实现主方法类,在这里我们创建5个考生线程,并启动它们。我们并没有在Phaser初始化的时候指定并发线程数量,而是在创建线程的时候使用register()方法来注册到Phaser上。

public class Main{
    public static void main(String[] args) {
        Phaser phaser = new MyPhaser();

        Student[] students = new Student[5];
        Thread[] threads = new Thread[5];

        for (int i = 0; i < 5; i++) {
            students[i] = new Student(phaser);
            phaser.register();
            threads[i] = new Thread(students[i], "Student-" + i);
        }

        for (int i = 0; i < 5; i++) {
            threads[i].start();
        }

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

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

查看日志

Student-4: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-0: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-2: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-1: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Student-3: Has arrived to the exam. Sat Nov 26 19:51:06 CST 2016
Phaser: The exam are going to start. The 5 students are ready.
Student-3: is going to do the first exercise.
Student-0: is going to do the first exercise.
Student-0: has done the first exercise.
Student-4: is going to do the first exercise.
Student-2: is going to do the first exercise.
Student-1: is going to do the first exercise.
Student-1: has done the first exercise.
Student-4: has done the first exercise.
Student-3: has done the first exercise.
Student-2: has done the first exercise.
Phaser: All the studnets have finished the first exercies.
Student-2: is going to do the second exercise.
Student-0: is going to do the second exercise.
Student-4: is going to do the second exercise.
Student-1: is going to do the second exercise.
Student-1: has done the second exercise.
Student-3: is going to do the second exercise.
Student-2: has done the second exercise.
Student-0: has done the second exercise.
Student-4: has done the second exercise.
Student-3: has done the second exercise.
Phaser: All the students have finished the second exercies.
Student-3: is going to do the third exercise.
Student-2: is going to do the third exercise.
Student-1: is going to do the third exercise.
Student-0: is going to do the third exercise.
Student-4: is going to do the third exercise.
Student-4: has finished the exam.
Student-0: has finished the exam.
Student-2: has finished the exam.
Student-1: has finished the exam.
Student-3: has finished the exam.
Phaser: All the students have finished the exam.
Main: The phaser has finished: true.

我们尝试把第一场考试执行完毕后的onAdvance方法返回值改为true试试结果,可以看到所有线程执行完第二场考试之后直接就开始执行第三场考试了,并没有等待其他线程都执行完毕第二场考试。

Student-4: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-3: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-1: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-2: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Student-0: Has arrived to the exam. Sat Nov 26 19:46:25 CST 2016
Phaser: The exam are going to start. The 5 students are ready.
Student-0: is going to do the first exercise.
Student-2: is going to do the first exercise.
Student-4: is going to do the first exercise.
Student-3: is going to do the first exercise.
Student-1: is going to do the first exercise.
Student-1: has done the first exercise.
Student-0: has done the first exercise.
Student-2: has done the first exercise.
Student-4: has done the first exercise.
Student-3: has done the first exercise.
Phaser: All the studnets have finished the first exercies.
Student-3: is going to do the second exercise.
Student-2: is going to do the second exercise.
Student-0: is going to do the second exercise.
Student-1: is going to do the second exercise.
Student-4: is going to do the second exercise.
Student-3: has done the second exercise.
Student-3: is going to do the third exercise.
Student-1: has done the second exercise.
Student-1: is going to do the third exercise.
Student-0: has done the second exercise.
Student-0: is going to do the third exercise.
Student-0: has finished the exam.
Student-2: has done the second exercise.
Student-2: is going to do the third exercise.
Student-4: has done the second exercise.
Student-4: is going to do the third exercise.
Student-3: has finished the exam.
Student-2: has finished the exam.
Student-1: has finished the exam.
Student-4: has finished the exam.
Main: The phaser has finished: true.

 

© 著作权归作者所有

阿拉德大陆的魔法师
粉丝 27
博文 91
码字总数 83019
作品 0
西城
程序员
私信 提问
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
734
1
Java并发编程(一)------并发编程面临的问题

并发编程面临的问题 并发编程是为了让程序运行得更快,但是并不是启动更多的线程就能让程序最大限度的并发执行,通常在并发编程中会遇到下面的问题. 1.1 上下文切换 CPU通过时间片非配算法来循...

PrivateO2
2018/12/04
22
0
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
689
1
干货系列1:Java互联网网站开发工程师 的技术提高与晋升路线(技术专精)

前几天写了自己对于Java软件开发工程师职业发展规划方面的一些感悟,陆续收到一些反馈,希望我能再就Java工程师不同的开发(职责)方向谈谈职业发展问题。(上一篇:Java软件开发工程师的自我...

半饱即好
2018/06/26
0
0
Part 001: 并发编程面临的挑战

并发编程的目的是为了让程序执行的更快,而不是启动更多的线程让程序最大幅度的并发执行。 1.上下文切换 CPU通过时间片分配算法来循环执行任务,任务从保存到再加载的过程就是一次上下文切换...

liululee
02/13
26
0

没有更多内容

加载失败,请刷新页面

加载更多

小知识:讲述Linux命令别名与资源文件的区别

别名 别名是命令的快捷方式。为那些需要经常执行,但需要很长时间输入的长命令创建快捷方式很有用。语法是: alias ppp='ping www.baidu.com' 它们并不总是用来缩短长命令。重要的是,你将它...

老孟的Linux私房菜
24分钟前
2
0
《JAVA核心知识》学习笔记(6. Spring 原理)-5

它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。 6.1.1. Spring 特点 6.1.1.1. 轻量级 6.1.1.2. 控制反转 6.1.1....

Shingfi
26分钟前
2
0
Excel导入数据库数据+Excel导入网页数据【实时追踪】

1.Excel导入数据库数据:数据选项卡------>导入数据 2.Excel导入网页数据【实时追踪】:

东方墨天
34分钟前
4
1
正则表达式如何匹配一个单词存在一次或零次并且不占捕获组位置

正则表达式如何匹配一个单词存在一次或零次并且不占捕获组位置 今天要用正则表达式实现匹配一个词出现一次或者不出现的情况,但是又不仅仅是这么简单的需求。先详细说下我这种情况吧,也许有...

Airship
40分钟前
5
0
第八讲:asp.net C# web 读取文件

本讲主要讲解如何在asp.net页面上传文件。 首先,前台页面: 其次,后台页面: 结果: 1、前台效果: 2、后台结果:

刘日辉
51分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部