《java7并发编程实战》线程辅助类之Phaser

来源:互联网 发布:网络购物应用 编辑:程序博客网 时间:2024/05/17 23:32
package comsys.net.hq.day1025;import java.io.File;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.concurrent.Phaser;import java.util.concurrent.TimeUnit;/** * 在该练习中的目标是在三个不同的文件夹及其子文件夹中查找过去24小时内修改过扩展名为.log的文件。 * 这个任务分成以下三个步骤: * 1、在指定的文件夹及其子文件夹中获得扩展名为.log的文件; * 2、对第一步的结果进行过滤,删除修改时间超过24小时的文件; * 3、将结果打印到控制台。 * 该练习的目的是学习多线程辅助类Phaser * @author Administrator * *//** * 文件查找类 * @author Administrator * */class FileSearch implements Runnable{//文件夹路径private String initPath;//后缀名private String end;//找到的文件的路径集合private List<String> results;//用于控制任务不同阶段的同步private Phaser phaser;public FileSearch(String initPath, String end, Phaser phaser) {super();this.initPath = initPath;this.end = end;this.results = new ArrayList<>();this.phaser = phaser;}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{fileProcess(list[i]);}}}}private void fileProcess(File file) {if(file.getName().endsWith(end)){results.add(file.getAbsolutePath());}}private void filterResults(){List<String> newResults = new ArrayList<>();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)){newResults.add(results.get(i));}}results = newResults;}/* * 检查结果列表的长度,如果是0,将没有找到任何文件的信息打印到控制台,并且调用Phaser对象的arriveAndDeregister() * 方法,来通知Phaser对象线程已经结束这个阶段,并且将不再参与接下来的阶段操作 * 如果结果集部不为空,则将查找的文件数打印到控制台,并且调用Phaser对象的arriveAwaitAdvance() * 方法,来通知Phaser对象当前线程已经完成了当前阶段,需要被阻塞直到其他线程也都完成当前阶段 */private boolean checkResults(){if(results.isEmpty()){System.out.println(Thread.currentThread().getName()+" 阶段 "+phaser.getPhase()+": 0个返回值");phaser.arriveAndDeregister();return false;}else{System.out.println(Thread.currentThread().getName()+" 阶段"+phaser.getPhase()+":"+results.size()+"个返回值");phaser.arriveAndAwaitAdvance();return true;}}/* * 将找到的结果元素打印到控制台 */private void showInfo(){for(int i = 0 ; i < results.size();i++){File file = new File(results.get(i));System.out.println(Thread.currentThread().getName()+":文件路径"+file.getAbsolutePath());}phaser.arriveAndAwaitAdvance();}@Overridepublic void run() {//等待查找工作所在的所有线程都被创建后再开始phaser.arriveAndAwaitAdvance();System.out.println(Thread.currentThread().getName()+":开始查找。。。");File file = new File(initPath);if(file.isDirectory()){directoryProcess(file);}//使用checkResults()方法检查结果集是不是空的,如果是,结束对应线程,并使用关键字return返回if(!checkResults()){return;}//查找24小时内修改的文件filterResults();if(!checkResults()){return;}//打印结果集showInfo();phaser.arriveAndDeregister()System.out.println(Thread.currentThread().getName()+"查找完毕!");}}public class PhaserDemo {public static void main(String[] args) {//3为有三个线程参与,这个数字通知Phaser在唤醒所有休眠线程进行下一阶段之前,必须执行arriveAndAwaitAdvance()方法的线程数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(documents,"Documents");documentsThread.start();try{systemThread.join();appsThread.join();documentsThread.join();}catch(InterruptedException e){}System.out.println("phaser是否终止:"+phaser.isTerminated());}}

总结:

new Phaser(number) 共有number个线程被注册参与同步任务,每一个步骤必须要等到number个线程完成才进行下一步骤,如果调用.arriveAndDeregister() ,phaser内部线程注册数将减1,即减少一个下一阶段要执行任务的线程

phaser.arriveAndDeregister() 方法:告诉phaser对象,当前线程已经完成该阶段任务,并且不执行下阶段任务,线程注册数减一

phaser.arriveAndAwaitAdvance()方法,告诉phaser对象,当前线程已经完成该阶段任务,并且休眠等待其他线程完成该阶段任务。

phaser.isTerminated()方法,检测phaser内部线程注册数是否为0,如果为0,返回true。

一个phaser对象又两种状态:

活跃态(active):当存在参与同步的线程的时候,Phaser就是活跃的,并且在每个阶段结束的时候进行同步。

终止态(termination)当所有参与同步的线程都取消注册的时候,phaser就处于终止态。

0 0