Callables and Futures


A Runnable encapsulates a task that runs asynchronously; you can think of it as an asynchronous method with no parameters and no return value. A Callable is similar to a Runnable, but it returns a value. The Callable interface is a parameterized type, with a single method call.

 public interface Callable<V> {    V call() throws Exception; } 

The type parameter is the type of the returned value. For example, a Callable<Integer> represents an asynchronous computation that eventually returns an Integer object.

A Future holds the result of an asynchronous computation. You use a Future object so that you can start a computation, give the result to someone, and forget about it. The owner of the Future object can obtain the result when it is ready.

The Future interface has the following methods:

 public interface Future<V> {    V get() throws . . .;    V get(long timeout, TimeUnit unit) throws . . .;    void cancel(boolean mayInterrupt);    boolean isCancelled();    boolean isDone(); } 

A call to the first get method blocks until the computation is finished. The second method throws a TimeoutException if the call timed out before the computation finished. If the thread running the computation is interrupted, both methods throw an InterruptedException. If the computation has already finished, then get returns immediately.

The isDone method returns false if the computation is still in progress, TRue if it is finished.

You can cancel the computation with the cancel method. If the computation has not yet started, it is canceled and will never start. If the computation is currently in progress, then it is interrupted if the mayInterrupt parameter is true.

The FutureTask wrapper is a convenient mechanism for turning a Callable into both a Future and a Runnableit implements both interfaces. For example,

 Callable<Integer> myComputation = . . .; FutureTask<Integer> task = new FutureTask<Integer>(myComputation); Thread t = new Thread(task); // it's a Runnable t.start(); . . . Integer result = task.get(); // it's a Future 

The program in Example 1-7 puts these concepts to work. This program is similar to the preceding example that found files containing a given keyword. However, now we will merely count the number of matching files. Thus, we have a long-running task that yields an integer valuean example of a Callable<Integer>.

 class MatchCounter implements Callable<Integer> {    public MatchCounter(File directory, String keyword) { . . . }    public Integer call() { . . . } // returns the number of matching files } 

Then we construct a FutureTask object from the MatchCounter and use it to start a thread.

 FutureTask<Integer> task = new FutureTask<Integer>(counter); Thread t = new Thread(task); t.start(); 

Finally, we print the result.

 System.out.println(task.get() + " matching files."); 

Of course, the call to get blocks until the result is actually available.

Inside the call method, we use the same mechanism recursively. For each subdirectory, we produce a new MatchCounter and launch a thread for it. We also stash the FutureTask objects away in an ArrayList<Future<Integer>>. At the end, we add up all results:

 for (Future<Integer> result : results)    count += result.get(); 

Each call to get blocks until the result is available. Of course, the threads run in parallel, so there is a good chance that the results will all be available at about the same time.

Example 1-7. FutureTest.java

[View full width]

   1. import java.io.*;   2. import java.util.*;   3. import java.util.concurrent.*;   4.   5. public class FutureTest   6. {   7.    public static void main(String[] args)   8.    {   9.       Scanner in = new Scanner(System.in);  10.       System.out.print("Enter base directory (e.g. /usr/local/jdk5.0/src): ");  11.       String directory = in.nextLine();  12.       System.out.print("Enter keyword (e.g. volatile): ");  13.       String keyword = in.nextLine();  14.  15.       MatchCounter counter = new MatchCounter(new File(directory), keyword);  16.       FutureTask<Integer> task = new FutureTask<Integer>(counter);  17.       Thread t = new Thread(task);  18.       t.start();  19.       try  20.       {  21.          System.out.println(task.get() + " matching files.");  22.       }  23.       catch (ExecutionException e)  24.       {  25.          e.printStackTrace();  26.       }  27.       catch (InterruptedException e) {}  28.    }  29. }  30.  31. /**  32.    This task counts the files in a directory and its subdirectories that contain a  given keyword.  33. */  34. class MatchCounter implements Callable<Integer>  35. {  36.    /**  37.       Constructs a MatchCounter.  38.       @param directory the directory in which to start the search  39.       @param keyword the keyword to look for  40.    */  41.    public MatchCounter(File directory, String keyword)  42.    {  43.       this.directory = directory;  44.       this.keyword = keyword;  45.    }  46.  47.    public Integer call()  48.    {  49.       count = 0;  50.       try  51.       {  52.          File[] files = directory.listFiles();  53.          ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>();  54.  55.          for (File file : files)  56.             if (file.isDirectory())  57.             {  58.                MatchCounter counter = new MatchCounter(file, keyword);  59.                FutureTask<Integer> task = new FutureTask<Integer>(counter);  60.                results.add(task);  61.                Thread t = new Thread(task);  62.                t.start();  63.             }  64.             else  65.             {  66.                if (search(file)) count++;  67.             }  68.  69.          for (Future<Integer> result : results)  70.             try  71.             {  72.                count += result.get();  73.             }  74.             catch (ExecutionException e)  75.             {  76.                e.printStackTrace();  77.             }  78.       }  79.       catch (InterruptedException e) {}  80.       return count;  81.    }  82.  83.    /**  84.       Searches a file for a given keyword.  85.       @param file the file to search  86.       @return true if the keyword is contained in the file  87.    */  88.    public boolean search(File file)  89.    {  90.       try  91.       {  92.          Scanner in = new Scanner(new FileInputStream(file));  93.          boolean found = false;  94.          while (!found && in.hasNextLine())  95.          {  96.             String line = in.nextLine();  97.             if (line.contains(keyword)) found = true;  98.          }  99.          in.close(); 100.          return found; 101.       } 102.       catch (IOException e) 103.       { 104.          return false; 105.       } 106.    } 107. 108.    private File directory; 109.    private String keyword; 110.    private int count; 111. } 


 java.util.concurrent.Callable<V> 5.0 

  • V call()

    runs a task that yields a result.


 java.util.concurrent.Future<V> 5.0 

  • V get()

  • V get(long time, TimeUnit unit)

    gets the result, blocking until it is available or the given time has elapsed. The second method throws a TimeoutException if it was unsuccessful.

  • boolean cancel(boolean mayInterrupt)

    attempts to cancel the execution of this task. If the task has already started and the mayInterrupt parameter is true, it is interrupted. Returns true if the cancellation was successful.

  • boolean isCancelled()

    returns true if the task was canceled before it completed.

  • boolean isDone()

    returns true if the task completed, through normal completion, cancellation, or an exception.


 java.util.concurrent.FutureTask<V> 5.0 

  • FutureTask(Callable<V> task)

  • FutureTask(Runnable task, V result)

    constructs an object that is both a Future<V> and a Runnable.



    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net