interface instead. Its call
method returns a value
ExecutorService executor = Executors.newFixedThreadPool();
Callable<V> task = ...;
Future<V> result = executor.submit(task);
As a bonus, the call method can throw arbitrary exceptions which can be
relayed to the code that obtains the result.
When you submit the task, you get a futureāan object that represents a
computation whose result will be available at some future time. The Future
interface has the following methods:
V get() throws InterruptedException, ExecutionException
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
boolean cancel(boolean mayInterruptIfRunning)
boolean isCancelled()
boolean isDone()
Example Searching files in dir with Futures
String word = ...;
Set<Path> paths = ...;
List<Callable<Long>> tasks = new ArrayList<>();
for (Path p : paths) tasks.add(
() -> { return number of occurrences of word in p });
List<Future<Long>> results = executor.invokeAll(tasks);
// This call blocks until all tasks have completed
long total = 0;
for (Future<Long> result : results) total += result.get();
import java.io.File;
import java.io.FileInputStream;
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.Future;
import java.util.concurrent.FutureTask;
public class FutureTest {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Please enter directory (e.g. /usr/local/jdk7.0/src): ");
String dir = input.nextLine();
System.out.print("Please enter keyword (e.g. myFile): ");
String keyword = input.nextLine();
MatchCounter countFiles = new MatchCounter(new File(dir), keyword);
FutureTask<Integer> tsk = new FutureTask<Integer>(countFiles);
Thread thread = new Thread(tsk);
thread.start();
try {
System.out.println(tsk.get() + " matching files.");
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
}
}
}
/**
* This task counts the files in a directory and its subdirectories that contain
* a given keyword.
*/
class MatchCounter implements Callable<Integer> {
/**
*
* dir the directory in which to start the search
* keyword the keyword to look for
*
*/
private File dir;
private String keyword;
private int counter;
public MatchCounter(File directory, String keyword) {
this.dir = directory;
this.keyword = keyword;
}
public Integer call() {
counter = 0;
try {
File[] files = dir.listFiles();
ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();
for (File file : files) {
if (file.isDirectory()) {
MatchCounter counter = new MatchCounter(file, keyword);
FutureTask<Integer> task = new FutureTask<Integer>(counter);
results.add(task);
Thread t = new Thread(task);
t.start();
} else {
if (search(file)) {
counter++;
}
}
}
for (Future<Integer> result : results) {
try {
counter += result.get();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
} catch (InterruptedException e) {
}
return counter;
}
/**
* Searches a file for a given keyword.
*
* file the file to search
* returns true if the keyword is contained in the file
*/
public boolean search(File file) {
try {
System.out.println(file.getCanonicalPath());
Scanner in = new Scanner(new FileInputStream(file));
boolean found = false;
while (!found && in.hasNextLine()) {
String line = in.nextLine();
if (line.contains(keyword)) {
found = true;
}
}
in.close();
return found;
} catch (IOException e) {
return false;
}
}
}