并发同步工具之Phaser

 

Phaser是一个可重用同步屏障,类似于CyclicBarrier、CountDownLatch,但是使用起来更灵活。

A reusable synchronization barrier, similar in functionality to
 * {@link java.util.concurrent.CyclicBarrier CyclicBarrier} and
 * {@link java.util.concurrent.CountDownLatch CountDownLatch}
 * but supporting more flexible usage.
<p><b>Registration.</b> Unlike the case for other barriers, the
 * number of parties <em>registered</em> to synchronize on a phaser
 * may vary over time.  Tasks may be registered at any time (using
 * methods {@link #register}, {@link #bulkRegister}, or forms of
 * constructors establishing initial numbers of parties), and
 * optionally deregistered upon any arrival (using {@link
 * #arriveAndDeregister}).  As is the case with most basic
 * synchronization constructs, registration and deregistration affect
 * only internal counts; they do not establish any further internal
 * bookkeeping, so tasks cannot query whether they are registered.
 * (However, you can introduce such bookkeeping by subclassing this
 * class.)

 

 

 

Phaser主要接口如下

  • arriveAndAwaitAdvance() 当前线程当前阶段执行完毕,等待其它线程完成当前阶段。如果当前线程是该阶段最后一个未到达的,则该方法直接返回下一个阶段的序号(阶段序号从0开始),同时其它线程的该方法也返回下一个阶段的序号。
  • arriveAndDeregister() 该方法立即返回下一阶段的序号,并且其它线程需要等待的个数减一,并且把当前线程从之后需要等待的成员中移除。如果该Phaser是另外一个Phaser 的子Phaser(层次化Phaser会在后文中讲到),并且该操作导致当前Phaser的成员数为0,则该操作也会将当前Phaser从其父 Phaser中移除。
  • arrive() 该方法不作任何等待,直接返回下一阶段的序号。
  • awaitAdvance(int phase) 该方法等待某一阶段执行完毕。如果当前阶段不等于指定的阶段或者该Phaser已经被终止,则立即返回。该阶段数一般由arrive()方法或者arriveAndDeregister()方法返回。返回下一阶段的序号,或者返回参数指定的值(如果该参数为负数),或者直接返回当前阶段序号(如果当前Phaser已经被终止)。
  • awaitAdvanceInterruptibly(int phase) 效果与awaitAdvance(int phase)相当,唯一的不同在于若该线程在该方法等待时被中断,则该方法抛出InterruptedException
  • awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit) 效果与awaitAdvanceInterruptibly(int phase)相当,区别在于如果超时则抛出TimeoutException
  • bulkRegister(int parties) 注册多个party。如果当前phaser已经被终止,则该方法无效,并返回负数。如果调用该方法时,onAdvance方法正在执行,则该方法等待其执行完毕。如果该Phaser有父Phaser则指定的party数大于0,且之前该Phaser的party数为0,那么该Phaser会被注册到其父Phaser中。
  • forceTermination() 强制让该Phaser进入终止状态。已经注册的party数不受影响。如果该Phaser有子Phaser,则其所有的子Phaser均进入终止状态。如果该Phaser已经处于终止状态,该方法调用不造成任何影响。

玩具代码

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;

//Phaser类提供的同步线程机制是在每个步骤的末端, 所以全部的线程都完成第一步后,才能开始执行第二步。

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;
		results = new ArrayList<>();
	}
	
	//根据目录查找文件
	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());
		}
	}
	
	//过滤超过24小时的数据
	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.MICROSECONDS.convert(1, TimeUnit.DAYS)){
				newResults.add(results.get(i));
			}
		}
		results = newResults;
	}
	
	private boolean checkResults(){
		//检查文件列表
		if(results.isEmpty()){
			System.out.printf("%s: Phase %d: 0 results.\n", 
					Thread.currentThread().getName(),phaser.getPhase());
			System.out.printf("%s: Phase %d: 0 End.\n", 
					Thread.currentThread().getName(),phaser.getPhase());
			//通知phaser,当前工作已经完成,并且在不参与下一个阶段的工作。
			phaser.arriveAndDeregister();
			return false;
		}else{
			System.out.printf("%s: Phase %d: 0 results.\n", 
					Thread.currentThread().getName(),phaser.getPhase());

			//通知phaser,当前工作已经完成,并且在等待其他线程完成。
			phaser.arriveAndAwaitAdvance();
			return true;
		}
	}
	
	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());
		}
		phaser.arriveAndAwaitAdvance();
	}
	
	
	@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);
		}
		
		if(!checkResults()){
			return;
		}
		
		filterResults();
		if(!checkResults()){
			return;
		}
		
		showInfo();
		phaser.arriveAndDeregister();
		System.out.printf("%s:Work completed.\n", Thread.currentThread().getName		
	}

	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(documents,"documents");
		documentsThread.start();
				
		//等待三个线程结束
		try{
			systemThread.join();
			appsThread.join();
			documentsThread.join();
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		
		System.out.printf("Terminated:%s", phaser.isTerminated());
	}

}

 

你可能感兴趣的:(并发同步工具之Phaser)