|
| |
Here's an example of the use of these interfaces and classes.
We've changed the previous MatchCounter example
to use these features, and called it MatchCounterPoolDemo:
package threads;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
/**
* A class to represent a Callable value that returns the count
* of files in a directory and its subdirectories that contain
* a specified keyword.
*/
public class MatchCounterPoolDemo implements Callable<Integer>
{
/**
* Main entry point
*/
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Starting directory? ");
String directory = in.nextLine();
System.out.print("Keyword? ");
String keyword = in.nextLine();
ExecutorService pool = Executors.newCachedThreadPool();
MatchCounterPoolDemo counter =
new MatchCounterPoolDemo(new File(directory), keyword, pool);
Future<Integer> result = pool.submit(counter);
try
{
System.out.println( result.get() + " files contained '" + keyword + "'");
}
catch (ExecutionException ee)
{
ee.printStackTrace();
}
catch (InterruptedException ie)
{
System.err.println("Execution interrupted");
}
pool.shutdown();
int largestPoolSize = ((ThreadPoolExecutor) pool).getLargestPoolSize();
System.out.println("Largest pool size: " + largestPoolSize);
}
/**
* Creates a new instance of MatchCounterPoolDemo.
*
* @param directory the directory in which to start the search
* @param keyword the keyword to search for.
* @param pool the thread pool to use.
*/
public MatchCounterPoolDemo(File directory, String keyword, ExecutorService pool)
{
m_directory = directory;
m_keyword = keyword;
m_pool = pool;
}
/**
* Implements the required Callable method
*/
public Integer call()
{
m_count = 0;
try
{
// Get list of files in current directory that match the file filter
File[] files = m_directory.listFiles( new FileFilter()
{
public boolean accept(File file)
{
return file.isDirectory() || file.getName().endsWith(".java");
}
}
);
// Create a results array
ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();
// Go through the files, doing a recursive and multi-threaded search.
for (File file : files)
{
if (file.isDirectory())
{
// Use another MatchCounterPoolDemo and another thread to search
// this directory.
MatchCounterPoolDemo counter =
new MatchCounterPoolDemo(file, m_keyword, m_pool);
Future<Integer> result = m_pool.submit(counter);
results.add(result);
}
else
{
if (search(file))
m_count++;
}
}
// Go through the Future results and accumulate the counts
for (Future<Integer> result : results)
{
try
{
m_count += result.get(); // Blocks until result available
}
catch (ExecutionException ee)
{
ee.printStackTrace();
}
}
}
catch (InterruptedException ie)
{
// Ignore
}
return m_count;
}
/**
* Searches the specified file for a given keyword.
*
* @param file the file to search
* @return true if the keyword was found in the file.
*/
private boolean search(File file)
{
Scanner in = null;
boolean found = false;
try
{
in = new Scanner( new FileReader(file) );
while (!found && in.hasNextLine())
{
String line = in.nextLine();
if (line.contains(m_keyword))
found = true;
}
}
catch (IOException ioe)
{
// Do nothing (results in found being returned false)
}
finally
{
if (in != null)
in.close();
}
return found;
}
//////// Private data //////////
private File m_directory;
private String m_keyword;
private ExecutorService m_pool;
private int m_count;
}
|
which produces, under similar conditions to the previous one:
27 files contained 'thread'
Largest pool size: 3
(I added one file since the last output.)
|