Java FutureTask example
Java 5 introduced the concurrent package for more efficient multi-threading. The executor framework and callable/Future interfaces were covered in the post entitled
Java 5 Executor framework
Q. What is the difference between Future and FutureTask in asynchronous processing?
A. Future is the interface and FutureTask is the base implementation of the Future with methods to start and cancel a computation. The FutureTask provides asynchronous computation with methods to start and cancel a computation, query to see if the computation is complete, and retrieve the result of the computation. The result can only be retrieved when the computation has completed. The get method will block if the computation has not yet completed. Once the computation has completed, the computation cannot be restarted or cancelled.
Here is an example with 2 tasks. One is an internal short task that takes ~1 second. The second task is an external long running task taking 4 ~ 10 seconds. It is imperative that long running tasks need to have proper processing timeouts.
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; public class FutureTaskExample { // inner class static class InternalProcess implements Callable&t;Integer> { @Override public Integer call() throws Exception { // just to simulate short internal process TimeUnit.SECONDS.sleep(1); return 2; } } // inner class static class ExternalProcess implements Callable&t;Integer> { @Override public Integer call() throws Exception { // just to simulate long running external process TimeUnit.SECONDS.sleep(15); return 12; } } public static void main(String[] args) { InternalProcess callable1 = new InternalProcess(); ExternalProcess callable2 = new ExternalProcess(); FutureTask&t;Integer> futureTask1 = new FutureTask&t;Integer>(callable1); FutureTask&t;Integer> futureTask2 = new FutureTask&t;Integer>(callable2); // create a fixed thread pool with 2 threads ExecutorService executor = Executors.newFixedThreadPool(2); // add future tasks to the pool executor.execute(futureTask1); executor.execute(futureTask2); while (true) { try { if (futureTask1.isDone() && futureTask2.isDone()) { System.out.println("Shutting down the executor."); // shut down executor service executor.shutdown(); return; } //if not done do it once if (!futureTask1.isDone()) { // wait indefinitely for future task to complete System.out.println("Task1 output = " + futureTask1.get()); } System.out.println("Waiting for FutureTask2 to complete"); //try the external task with the timeout of 5 seconds Integer result = futureTask2.get(5, TimeUnit.SECONDS); if (result != null) { System.out.println("Task2 output = " + result); } } catch (InterruptedException ie) { ie.printStackTrace(); } catch (TimeoutException e) { // do nothing as we want to process it asynchronously // if you want to time out then uncomment 2 lines //System.out.println("Cancelling Task2 due to timeout"); //futureTask2.cancel(true); // true means interrupt } catch (ExecutionException e) { e.printStackTrace(); } } } }
The output is
Task1 output = 2 Waiting for FutureTask2 to complete Waiting for FutureTask2 to complete Waiting for FutureTask2 to complete Task2 output = 12 Shutting down the executor.
If you re-run it by uncommenting the last 2 lines in the TimeoutException catch block, you will get task2 cancelled.
Task1 output = 2 Waiting for FutureTask2 to complete Cancelling Task2 due to timeout Shutting down the executor.
Labels: Multi-threading
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home