版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。






package com.bird.concursey.charpet5;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

 * This class implements the operation of searching for files with a determined
 * extension modified in the last 24 hours in a folder and its subfolders
 * @author bird 2014年9月22日 下午10:12:18
public class FileSearch implements Runnable {
	// store the folder in which the search operation will begin.
	private String initPath;
	// store the extension of the files we are going to look for.
	private String end;
	// store the full path of the files we will find with the desired
	// characteristics.
	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>();

	public void run() {
		//The search won't begin until all the threads have been created.
		System.out.printf("%s: Starting.\n",Thread.currentThread().getName());
		File file = new File(initPath);
		if(file.isDirectory()) {
		if(!checkResults()) {
		if(!checkResults()) {
		System.out.printf("%s: Work completed.\n",Thread.currentThread().getName());

	 * It receives a File object as a parameter and it processes all its files
	 * and subfolders.
	 * @param file
	private void directoryProcess(File file) {
		File files[] = file.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
				} else {

	 * checks if its extension is equal to the one we are looking for
	 * @param file
	private void fileProcess(File file) {
		if (file.getName().endsWith(end)) {

	 * deleting the files that were modified more than 24 hours ago
	private void filterResults() {
		List<String> newResults = 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)) {
		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: End.\n", Thread.currentThread().getName(), phaser.getPhase());
			return false;
			System.out.printf("%s: Phase %d: %d results.\n",Thread.currentThread().getName(),phaser.getPhase(),results.size());
			//this thread has finished the actual
			//phase and it wants to be blocked until all the participant threads in the phased
			//operation finish the actual phase.
			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());
	public static void main(String[] args) throws Exception {
		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:\\ProgramData", "log", phaser);
		Thread systemThread = new Thread(system, "System");
		Thread appsThread = new Thread(apps, "appsThread");
		Thread documentsThread = new Thread(documents, "documentsThread");
		System.out.println("Terminated: "+ phaser.isTerminated());

The program starts creating a Phaser object that will control the synchronization of the threads
at the end of each phase. The constructor of Phaser receives the number of participants as
a parameter. In our case, Phaser has three participants. This number indicates to Phaser
the number of threads that have to execute an arriveAndAwaitAdvance() method before
Phaser changes the phase and wakes up the threads that were sleeping.
Once Phaser has been created, we launch three threads that execute three different
FileSearch objects.

The first instruction in the run() method of this FileSearch object is a call to the
arriveAndAwaitAdvance() method of the Phaser object. As we mentioned earlier, the
Phaser knows the number of threads that we want to synchronize. When a thread calls this
method, Phaser decreases the number of threads that have to finalize the actual phase and
puts this thread to sleep until all the remaining threads finish this phase. Calling this method
at the beginning of the run() method makes none of the FileSearch threads begin their
job until all the threads have been created.

At the end of phase one and phase two, we check if the phase has generated results and the
list with the results has elements, or otherwise the phase hasn't generated results and the list
is empty. In the first case, the checkResults() method calls arriveAndAwaitAdvance()
as explained earlier. In the second case, if the list is empty, there's no point in the thread
continuing with its execution, so it returns. But you have to notify the phaser that there will be
one less participant. For this, we used arriveAndDeregister(). This notifies the phaser
that this thread has finished the actual phase, but it won't participate in the future phases, so
the phaser won't have to wait for it to continue.

At the end of the phase three implemented in the showInfo() method, there is a call to the
arriveAndAwaitAdvance() method of the phaser. With this call, we guarantee that all the
threads finish at the same time. When this method ends its execution, there is a call to the
arriveAndDeregister() method of the phaser. With this call, we deregister the threads
of the phaser as we explained before, so when all the threads finish, the phaser will have zero

Finally, the main() method waits for the completion of the three threads and calls the
isTerminated() method of the phaser. When a phaser has zero participants, it enters the
so called termination state and this method returns true. As we deregister all the threads of
the phaser, it will be in the termination state and this call will print true to the console.