Phaser允许并发多阶段任务。Phaser类机制是在每一步结束的位置对线程进行同步,当所有的线程都完成了这一步,才允许执行下一步。

  一个Phaser对象有两种状态:

  • 活跃态(Active):当存在参与同步的线程的时候,Phaser就是活跃的,并且在每个阶段结束的时候进行同步。
  • 终止态(Termination):当所有参与同步的线程都取消注册的时候,Phaser就处于终止态,在终止状态下,Phaser没有任何参与者。当Phaser对象onAdvance()方法返回True时,Phaser对象就处于终止态。当Phaser处于终止态时,同步方法arriveAndAwaitAdvance()会立即返回,而且不会做任何同步操作。

  Phaser对象的主要方法:

  • arrive():这个方法通知phaser对象一个参与者已经完成当前阶段,但是它不应该等待其他参与者都完成当前阶段任务。必须使用这个方法,因为它不会与其他线程同步。
  • awaitAdvance(int phase).如果传入的参数与当前阶段一直,这个方法将会将当前线程置于休眠,直到这个阶段的参与者都完成运行。如果传入的阶段参数与当前阶段不一致,立即返回。
  • arriveAndAwaitAdvance().当一个线程调用此方法时,Phaser对象将减1,并把这个线程至于休眠状态,直到所有其他线程完成这个阶段。
  • arriveAndDeregister().当一个线程调用此方法时,Phaser对象将减1,并且通知这个线程已经完成了当前语句,不会参加到下一个阶段中,因此phaser对象在开始下一个阶段时不会等待这个线程。
  • awaitAdvanceInterruptibly(int phase).这个方法跟awaitAdvance(int phase)一样,不同之处是,如果这个方法中休眠的线程被中断,它将抛出InterruptedException异常。
  • register():这个方法将一个新的参与者注册到phaser中,这个新的参与者将被当成没有执行完本阶段的线程。
  • bulkRegister(int Parties):这个方法将指定数目的参与者注册到Phaser中,所有的这些参与者都讲被当成没有执行完本阶段的线程。

  下面将通过具体的实例来讲解Phaser的用法。在实例中Phaser将同步三个并发任务。这三个任务将在三个不同的文件夹及其子文件夹中查找过去24小时内改过扩展名为。log的文件。这个任务分解为三个步骤:

  1.在指定文件夹及其子文件夹中获得扩展名为.log的文件。

  2.对第一步的结果过滤,删除修改时间超过24小时的文件。

  3.将结果打印数据到控制台。

public 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) {
this.initPath = initPath;
this.end = end;
this.phaser = phaser;
this.results = new ArrayList<String>();
} private void direactoryProcess(File file) {
File list[] = file.listFiles();
if (list != null) {
for (File file2 : list) {
if (file2.isDirectory()) {
direactoryProcess(file2);
} else {
fileProcess(file2);
}
}
}
} private void fileProcess(File file) {
if (file.getName().endsWith(end)) {
results.add(file.getAbsolutePath());
}
} 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 lastModifyTime = file.lastModified();
if (actualDate - lastModifyTime < TimeUnit.MICROSECONDS.convert(1,
TimeUnit.DAYS)) {
newResult.add(results.get(i));
}
}
results = newResult;
} private boolean checkResults() {
if (results.isEmpty()) {
System.out.println(Thread.currentThread().getName() + ": Phase "
+ phaser.getPhase() + " 0 result");
System.out.println(Thread.currentThread().getName() + ": Phase "
+ phaser.getPhase() + " end");
phaser.arriveAndDeregister();
return false;
} else {
System.out.println(Thread.currentThread().getName() + ": Phase "
+ phaser.getPhase() + " " + results.size() + " result");
phaser.arriveAndAwaitAdvance();
return true;
}
} private void showInfo() {
for (int i = 0; i < results.size(); i++) {
System.out.println(Thread.currentThread().getName() + ":"
+ results.get(i));
}
phaser.arriveAndAwaitAdvance();
} @Override
public void run() {
phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName()+": Starting");
File file=new File(initPath);
if(file.isDirectory()){
direactoryProcess(file);
}
if(!checkResults()){
return;
}
filterResult();
if(!checkResults()){
return;
}
showInfo();
phaser.arriveAndDeregister();
System.out.println(Thread.currentThread().getName()+": Work completed");
}
}
public class PhaserMain {
public static void main(String[] args) {
Phaser phaser=new Phaser(3);
FileSearch system=new FileSearch("c:\\Windows", "log", phaser);
FileSearch apps=new FileSearch("C:\\Programs 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 (Exception e) {
e.printStackTrace();
}
System.out.println("Terminated:"+ phaser.isTerminated());
}
}

Phaser类详解的更多相关文章

  1. java之StringBuffer类详解

    StringBuffer 线程安全的可变字符序列. StringBuffer源码分析(JDK1.6): public final class StringBuffer extends Abstract ...

  2. java之AbstractStringBuilder类详解

    目录 AbstractStringBuilder类 字段 构造器 方法   public abstract String toString() 扩充容量 void  expandCapacity(in ...

  3. java之StringBuilder类详解

    StringBuilder 非线程安全的可变字符序列 .该类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍).如果可能,建议优先采用该类,因为在 ...

  4. Java String类详解

    Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...

  5. QAction类详解:

    先贴一段描述:Qt文档原文: Detailed Description The QAction class provides an abstract user interface action tha ...

  6. JAVAEE学习——struts2_01:简介、搭建、架构、配置、action类详解和练习:客户列表

    一.struts2是什么 1.概念 2.struts2使用优势以及历史 二.搭建struts2框架 1.导包 (解压缩)struts2-blank.war就会看到 2.书写Action类 public ...

  7. Struts2-整理笔记(二)常量配置、动态方法调用、Action类详解

    1.修改struts2常量配置(3种) 第一种 在str/struts.xml中添加constant标签 <struts> <!-- 如果使用使用动态方法调用和include冲突 - ...

  8. C# 内置 DateTime类详解

    C# 内置 DateTime类详解 摘抄自微软官方文档,用来方便自己查阅:网址:https://msdn.microsoft.com/zh-cn/library/system.datetime(v=v ...

  9. Android游戏开发之旅 View类详解

    Android游戏开发之旅 View类详解 自定义 View的常用方法: onFinishInflate() 当View中所有的子控件 均被映射成xml后触发 onMeasure(int, int) ...

随机推荐

  1. MyBatis快速入门(1):搭建环境和单表映射

    一.MyBatis简介    一说起对象关系映射框架,大家第一时间想到的肯定是Hibernate.Hibernate作为一个著名的框架,功能十分强大.我们只需要配置好实体类和数据表之间的关系,Hibe ...

  2. [SinGuLaRiTy] 2017-03-30 综合性测试

    [SinGuLaRiTy-1014] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 对于所有的题目:Time Limit:1s  |  Me ...

  3. VS 2017开发ASP.NET Core Web应用过程中发现的一个重大Bug

    今天试着用VS 2017去开发一个.net core项目,想着看看.net core的开发和MVC5开发有什么区别,然后从中发现了一个VS2017的Bug. 首先,我们新建项目,ASP.NET Cor ...

  4. Python JavaScript概述

    一.如何编写? 1.JavaScript代码存在形式 <!DOCTYPE html> <html> <head> <meta http-equiv=" ...

  5. python 三层架构说明

    三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:表现层(Presentation layer).业务逻辑层(Business Logic Layer) ...

  6. seo从业者发展方向

    对于很多朋友来说,seo就是一项比较简单的技能,内容+外链,就可以基本囊括seo的基本内容了.可能很多朋友对此不屑一顾,会说seo可是包含万象, 你需要懂网页设计.标签设计,分词优化.企业建站等等方面 ...

  7. oracle表空间扩容

    oracle在使用中会发现,表空间不足的情况:以下介绍了如何1.查询表空间使用率.剩余量:2.如何扩展表空间容量: 1.表空间容量指标查询 SELECT TABLESPACE_NAME "表 ...

  8. Linux - IP数据报报头及个字段的意义

    IP数据报的格式: IP 数据报的首部长度和数据长度都是可变长的,但总是4字节的整数倍. 对于IPv4 ,4位版本字段是4. (1)版本 占4位,指IP协议的版本.通信双方使用的IP协议版本必须一致. ...

  9. 单片机下载芯片max232,ch340,pl2303,hl340与下载接线

    开发板上的下载口位置一般都有很多 340,232等芯片,这些芯片都是干嘛用的呢? 普及:TTL电平    : 二进制电平,+5V等价于逻辑"1",0V等价于逻辑"0&qu ...

  10. C++ 窗口可改风格

    SetWindowLong(m_hWnd,GWL_STYLE,::GetWindowLong(m_hWnd,GWL_STYLE)& ~WS_MAXIMIZEBOX);//去掉最大化 GWL_S ...