java并发编程实战手册第三章同步辅助类Phaser
来源:互联网 发布:wol网络唤醒 编辑:程序博客网 时间:2024/06/06 05:10
java 1.7新增的特性
本案例简介:
5.并发阶段任务的运行(http://blog.csdn.net/escaflone/article/details/10418651)
Phaser允许执行并发多阶段的任务。当我们有并发任务并且需要分解成几步执行的时候,这种机制非常好。
Phaser类机制是在每一步结束的位置对线程进行同步,当所有的线程都完成了这一步,才允许执行下一步。
跟其他同步工具一样,必须对Phaser类中参与同步操作的任务数量进行初始化,不同的是,我们可以动态地增加或减少任务数量。
使用介绍:
4.Phaser : 把并发任务分成多个阶段运行,在开始下一个阶段之前,当前阶段的所有线程都必须执行完成。java 7中的新特性。
适用场景:
1.允许并发多阶段任务,当我们有并发任务并且需要分解成几步执行时,这种机制就非常有用。该机制是在每一步结束的位置对线程进行同步,当所有的线程都完成了这一步,才允许执行
下一步。
说明:在F/J框架中的子任务之间要进行同步,应该优先考虑Phaser。
Phaser把多个线程写作执行的任务划分成多个阶段,编程时演明确各个阶段的任务,每个阶段都可以有任意个参与者,
线程可以随时注册并参与到某个阶段,当一个阶段中所有线程都成功完成后,Phaser的onAdvance()被调用,
可以通过覆盖添加自定义处理逻辑(类似CyclicBarrier使用的Ruunable接口),然后Phaser类会自动进入下一个阶段,如此循环直到Phaser不再包含任何参与者
Phaser创建后,初试阶段编号为0,构造函数中指定初始参与个数。
主要方法
1.register(),bulkRegister():动态添加一个或者多个参与者,这些参与者将被当成没有执行完本阶段的线程。
2.arrive():某个参与完成任务后调用,该方法不会等待其他参与者都完成当前状态,所以不会与其他线程同步,应该小心使用。
3.arriveAndDeregister():任务完成,取消自己的注册。
4.arriveAndAwaitAdvance():自己完成等待其他参与者完成,进入阻塞状态,直到Phaser成功进入下一个阶段。
5.awaitAdvance(int phase):如果传入的阶段参数与当前节点一致,这个方法会将当前线程置入休眠,直到这个阶段的所有参与者都运行完成,如果传入的阶段参数与当前阶段
不一致,这个方法将立即返回。
6.awaitAdvanceInterruptibly(int phaser):这个方法与5是一样的,不同之处在于如果在这个方法中休眠的线程被中断,将抛出InterruptedException
7.forceTermination():该方法强制将phaser进入终止状态,这个方法不管phaser中是否存在注册的参与线程,当一个参与的线程出现错误的时候,强制终止phaser是很有意义的。
当一个phaser处于终止状态的时候,awaitAdvance()和arriveAndAwaitAdvance()方法会立即返回一个负数,而不是一个正值。
8.onAdvance():在Phaser阶段改变的时候会被自动执行,一般我们会重写这个方法用来在每个阶段改变的时候做一些事情。 该方法返回布尔值用来表明phaser是否终止,
false表示没有终止,因而线程可以继续执行其他的阶段,如果返回值为true,则phaser仍然唤醒等待的线程,但是状态已经变成终止状态了,所以继续调用phaser的方法将立即返回,
并且isTerminated()方法也将返回true
说明:awaitAdvance(),awaitAdvanceInterruptibly(),等待phaser进入下一个阶段,参数为当前阶段的编号,后者可以设置超时和处理中断请求。另外,Phaser的一个重要特征是多个Phaser可以组成树形结构,Phaser提供了构造方法来指定当前对象的父对象,当一个子对象参与者>0,会自动注册到父对象中,当子对象的参与者=0,自动解除注册。一个Phaser对象有两种状态 1.活跃状态(Active)当存在参与同步的线程的时候,Phaser就是活跃的,并且每一个阶段结束的时候进行同步。java API中并没有提到该状态 2.终止状态(Termination):当所有参与同步的线程都取消注册的时候,Phaser就处于终止状态了,这种状态下Phaser没有任何参与者。
一、并发阶段任务的运行
本实例同步三个并发任务,三个任务在三个不同的文件夹和子文件夹中查找过去24小时内修改过的扩展名为.log的文件。分三个步骤执行
1.获得.log文件
2.对1进行过滤,获得修改时间在24小时内的文件
3.将结果打印到控制台。
1.FileSearch: 文件查找类
public class FileSearch implements Runnable{ private String initPath; //存储查找的文件夹 private String end; //存储查找文件的扩展名 private Phaser phaser; //用来控制任务不同阶段的同步 private List<String> results; public FileSearch(String initPath, String end, Phaser phaser) { this.initPath = initPath; this.end = end; this.phaser = phaser; results = new ArrayList<String>(); } /** * * 作者:fcs * 描述:处理文件夹的所有文件夹和子文件夹,对于每个文件夹这个方法将递归调用,对于每个文件,这个方法 * 将调用fileProcess()方法 * 说明: * 返回: * 参数: * 时间:2015-4-23 */ private void directoryProcess(File file){ File list [] = file.listFiles(); if(list != null){ for(int i = 0;i < list.length;i++){ if(list[i].isDirectory()){ directoryProcess(list[i]); }else{ } } } } /** * * 作者:fcs * 描述:查找传入文件的对象的扩展名是不是我们指定的。 * 说明: * 返回: * 参数: * 时间:2015-4-23 */ private void fileProcess(File file){ if(file.getName().endsWith(end)){ results.add(file.getAbsolutePath()); } } /** * * 作者:fcs * 描述:对第一个阶段查找到的文件列表进行过滤,将不是过去24小时修改过的文件删除, * * 说明: * 返回: * 参数: * 时间:2015-4-23 */ private void filterResult(){ List<String> newResult = new ArrayList<String>(); long actualDate = new Date().getTime(); for(int i = 0;i < results.size();i++){ File file = new File(results.get(i)); long fileDate = file.lastModified(); if(actualDate - fileDate <TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)){ newResult.add(results.get(i)); } } results = newResult; } /** * * 作者:fcs * 描述:将在第一阶段和第二阶段结束的时候被调用 * 用来检查结果集是不是空的 * 说明:如果是空的则调用phaser.arriveAndDeregister()方法 * * 返回: * 参数: * 时间:2015-4-23 */ public boolean checkResult(){ if(results.isEmpty()){ System.out.printf("%s: phase %d: 0 results.\n",Thread.currentThread().getName(),phaser.getPhase()); System.out.printf("%s: Phase %d End.\n",Thread.currentThread().getName(),phaser.getPhase()); phaser.arriveAndDeregister(); return false; }else{ System.out.printf("%s:Phase %d: %d results.\n",Thread.currentThread().getName(),phaser.getPhase(),results.size()); /*通知phaser对象当前线程已经完成当前阶段,需要被阻塞直到其他线程也都完成当前阶段*/ phaser.arriveAndAwaitAdvance(); return true; } } /** * * 作者:fcs * 描述: * 说明:将结果集元素打印到控制台 * 返回: * 参数: * 时间:2015-4-23 */ private void showInfo(){ for(int i =0 ; i < results.size();i++){ File file = new File(results.get(i)); System.out.printf("%s: %s\n.",Thread.currentThread().getName(),file.getAbsolutePath()); } } @Override public void run() { phaser.arriveAndAwaitAdvance(); //调用该方法等待所有线程都被创建后再开始 System.out.printf("%s: Starting .\n",Thread.currentThread().getName()); File file = new File(initPath); if(file.isDirectory()){ directoryProcess(file); } //并发任务的第一阶段 //使用该方法检查结果集是不是空的,如果是结束对应线程,并且用关键字return if(!checkResult()){ return; } //并发任务的第二阶段 //使用该方法过滤结果集 filterResult(); if(!checkResult()){ return; } //并发任务的第三阶段 //使用该方法将最终的结果集打印到控制台,并且撤销线程的注册,然后将线程完成的信息打印到控制台 showInfo(); phaser.arriveAndDeregister(); System.out.printf("%s: work complete .\n",Thread.currentThread().getName()); } }
2.测试类
public class Main { public static void main(String[] args) { Phaser phaser = new Phaser(3); FileSearch system = new FileSearch("c:\\windows", "log", phaser); FileSearch apps = new FileSearch("c:\\Program Files", "log", phaser); FileSearch documents = new FileSearch("c:\\Documents And Settings","log",phaser); Thread systemThread = new Thread(system,"system"); systemThread.start(); Thread appsThread = new Thread(apps,"apps"); appsThread.start(); Thread documentsThread = new Thread(apps,"documents"); documentsThread.start(); try { systemThread.join(); appsThread.join(); documentsThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } }}
这里如果运行的话,有的电脑可能没有在24小时内修改过的.log文件。这里我模拟了一下;
二、并发阶段中的任务切换
1.自定义Phaser
package cn.fans.chapter3.six;import java.util.concurrent.Phaser;/** * * @author fcs * @date 2015-5-1 * 描述:并发阶段任务中的阶段切换 * 说明:继承Phaser对象,并重写onAdvance对象 */public class MyPhaser extends Phaser{ /** * 在每个阶段任务完成后,进入下一个阶段时会执行该方法 * 可以处理阶段性要处理的事情 */ @Override protected boolean onAdvance(int phase, int registeredParties) { switch(phase){ case 0: return studentsArrived(); case 1: return finishFirstExersize(); case 2: return finishSecondExersize(); case 3: return finishExam(); default : return true; } } private boolean studentsArrived(){ System.out.printf("Phaser: The exam are going to start. The Students are ready"); System.out.printf("Phaser: We have %d students.\n",getRegisteredParties()); return false; } private boolean finishFirstExersize(){ System.out.println("Phaser: All the students have finished the first exersie.\n"); System.out.println("Phaser: It's time for the second one\n"); return false; } private boolean finishSecondExersize(){ System.out.println("Phaser: All the students have finished the second exersie.\n"); System.out.println("Phaser: It's time for the second one\n"); return false; } private boolean finishExam(){ System.out.println("Phaser: All the students have finished the exam.\n"); System.out.println("Phaser: Thank you for your time\n"); return true; }}
2.学生类
package cn.fans.chapter3.six;import java.util.Date;import java.util.concurrent.Phaser;import java.util.concurrent.TimeUnit;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 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()); doExceercise1(); System.out.printf("%s: has down 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()); doExceercise2(); System.out.printf("%s: has down 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()); doExceercise3(); System.out.printf("%s: has down the second exercise %s.\n",Thread.currentThread().getName(),new Date()); phaser.arriveAndAwaitAdvance(); } private void doExceercise1(){ long duration = (long)(Math.random()*10); try { TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } } private void doExceercise2(){ long duration = (long)(Math.random()*10); try { TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } } private void doExceercise3(){ long duration = (long)(Math.random()*10); try { TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); } }}
3.测试类
public class Main { public static void main(String[] args) { MyPhaser myPhaser = new MyPhaser(); Student [] student = new Student[5]; for(int i =0 ;i< student.length;i++){ student[i] = new Student(myPhaser); //该方法并没有建立学生对象或者它对应的执行线程与phaser之间的关联。 //实际上phaser中的参与者数目只是一个数字,phaser与参与者不存在任何关联。 myPhaser.register(); //通过该方法将student线程对象注册到phaser对象中 } Thread threads [] = new Thread[student.length]; //创建5个线程 for(int i =0 ;i < student.length;i++){ threads[i] = new Thread(student[i],"student"+i); threads[i].start(); } //等待线程终止 for(int i =0 ;i< student.length;i++){ try { threads[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.printf("Main : The phaser has finished: %s \n",myPhaser.isTerminated()); }}
运行结果演示:
- java并发编程实战手册第三章同步辅助类Phaser
- java并发编程实战手册第三章同步辅助类--Semaphore
- java并发编程实战手册第三章同步辅助类Exchanger
- [笔记][Java7并发编程实战手册]第三章-线程同步辅助类-3.1概要
- Java并发编程-同步辅助类之Phaser
- Java并发编程-同步辅助类之Phaser
- java并发实战手册第三章(线程同步辅助类介绍)
- java 并发编程实战第三章同步辅助类CyclicBarrier解析
- 并发编程实战手册-线程同步辅助类之CyclicBarrier
- 《java7并发编程实战》线程辅助类之Phaser
- 《java并发编程实战》:线程同步辅助类之CountDownLatch
- java并发编程实战手册第三章---CountDownLatch使用
- 《java并发编程实战》:线程同步辅助类之信号量(semaphore)
- Java7并发编程指南——第三章:线程同步辅助类
- 【Java并发编程实战】—–“J.U.C”:Phaser
- 【Java并发编程实战】—–“J.U.C”:Phaser
- 【Java并发编程实战】-----“J.U.C”:Phaser
- [笔记][Java7并发编程实战手册]3.6 并发阶段任务的运行phaser
- hdu2457AC自动机+DP
- Git SSH Key生成步骤
- ********随便看看**********
- PyQt中QLabel背景与字体的一些设置
- 梯度下降 VS 随机梯度下降
- java并发编程实战手册第三章同步辅助类Phaser
- Mysql常识
- Android java代码优化问题探究
- [dp] poj 3661 Running
- Mac下常用命令收集箱
- 剑指offer--面试题7:用两个栈实现队列--Java实现
- J2EE开发常用开源框架技术
- Same Tree
- Cache Memory