A Technology Blog About Code Development, Architecture, Operating System, Hardware, Tips and Tutorials for Developers.

Friday, July 6, 2012

Concurrency: Callable and Future

7:06:00 PM Posted by Satish , , , No comments

Till Java 1.4, threads could be implemented by either implementing Runnable or extending Thread. This was quite simple, but had a serious limitation - They have a run method that cannot return values. Java 5 introduces the Callable interface, that allows users to return values from a thread. This post describes the Callable and Future interfaces and shows an example of how to use these to interfaces.

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

The call() method is the entry point into a Callable object, and it's return type is the type parameter set in the Callable object. To implement Callable with no return value, use Callable. Also, note that the call() method throws a checked exception, as compared to the run() method in Runnable which does not throw any exception. The Executors class contains utility methods to convert from other common forms to Callable classes. However, Callable cannot be used in place of a Runnable. Callable objects have to be invoked by ExecutorService. The Executor framework provides the Future interface to allow handling the cancellation and returns of a Callable object.
A Future represents the result of an asynchronous computation.

public interface Future {


//Attempts to cancel execution of this task.
boolean cancel(boolean mayInterruptIfRunning);


boolean isCancelled();


boolean isDone();


// Waits if necessary for the computation to complete,
//  and then retrieves its result.
V get() throws InterruptedException, ExecutionException;


// Waits if necessary for at most the given time for the computation
// to complete, and then retrieves its result, if available.
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

The result can be retrieved using method get() when the computation has completed, blocking if necessary until it is ready. If you would like to use a Future for the sake of cancellation but not provide a usable result, you can declare types of the form Future and return null as a result of the underlying task. The following example demonstrates the use of Callable and future. The first CallableImpl class implements the Callable interface, and returns an integer that is sent to it's constructor. The CallableTester class invokes the CallableImpl through an executor.

package org.satish.concurrency;


import java.util.concurrent.Callable;


public class CallableImpl implements Callable {


private String threadName;


CallableImpl(String i) {
threadName = i;


ExecutorService executor = new ScheduledThreadPoolExecutor(5);

Future future = null;
Callable callable;
for (int i = 0; i < 10000; i++) {
callable = new CallableImpl("Thread - " + i);
future = executor.submit(callable);
}


try {
System.out.println("Future value: " + future.get());
} catch (Exception e) {

e.printStackTrace();

}
}
}


CallableTester.java

LOG


Thread : Thread - 0 :: Looping Job No : 0
Thread : Thread - 1 :: Looping Job No : 0
Thread : Thread - 1 :: Looping Job No : 1
Thread : Thread - 1 :: Looping Job No : 2
Thread : Thread - 1 :: Looping Job No : 3
Thread : Thread - 1 :: Looping Job No : 4
Thread : Thread - 1 :: Looping Job No : 5
Thread : Thread - 1 :: Looping Job No : 6
Thread : Thread - 1 :: Looping Job No : 7
Thread : Thread - 1 :: Looping Job No : 8
Thread : Thread - 1 :: Looping Job No : 9
Thread : Thread - 0 :: Looping Job No : 1
Thread : Thread - 0 :: Looping Job No : 2
Thread : Thread - 0 :: Looping Job No : 3
Thread : Thread - 0 :: Looping Job No : 4
Thread : Thread - 0 :: Looping Job No : 5
Thread : Thread - 0 :: Looping Job No : 6
Thread : Thread - 0 :: Looping Job No : 7
Thread : Thread - 0 :: Looping Job No : 8
Thread : Thread - 0 :: Looping Job No : 9
Thread : Thread - 6 :: Looping Job No : 0
Thread : Thread - 6 :: Looping Job No : 1
Thread : Thread - 6 :: Looping Job No : 2
Thread : Thread - 6 :: Looping Job No : 3
Thread : Thread - 6 :: Looping Job No : 4
Thread : Thread - 6 :: Looping Job No : 5
Thread : Thread - 6 :: Looping Job No : 6
Thread : Thread - 6 :: Looping Job No : 7
Thread : Thread - 6 :: Looping Job No : 8
Thread : Thread - 6 :: Looping Job No : 9
Thread : Thread - 2 :: Looping Job No : 0
Thread : Thread - 2 :: Looping Job No : 1
Thread : Thread - 2 :: Looping Job No : 2
Thread : Thread - 2 :: Looping Job No : 3
Thread : Thread - 2 :: Looping Job No : 4
Thread : Thread - 2 :: Looping Job No : 5
Thread : Thread - 2 :: Looping Job No : 6
Thread : Thread - 2 :: Looping Job No : 7
Thread : Thread - 2 :: Looping Job No : 8
Thread : Thread - 2 :: Looping Job No : 9
Thread : Thread - 7 :: Looping Job No : 0
Thread : Thread - 7 :: Looping Job No : 1
Thread : Thread - 7 :: Looping Job No : 2
Thread : Thread - 7 :: Looping Job No : 3
Thread : Thread - 7 :: Looping Job No : 4
Thread : Thread - 7 :: Looping Job No : 5
Thread : Thread - 7 :: Looping Job No : 6
Thread : Thread - 7 :: Looping Job No : 7
Thread : Thread - 7 :: Looping Job No : 8
Thread : Thread - 7 :: Looping Job No : 9
Thread : Thread - 5 :: Looping Job No : 0
Thread : Thread - 4 :: Looping Job No : 0
Thread : Thread - 4 :: Looping Job No : 1
Thread : Thread - 4 :: Looping Job No : 2
Thread : Thread - 4 :: Looping Job No : 3
Thread : Thread - 4 :: Looping Job No : 4
Thread : Thread - 4 :: Looping Job No : 5
Thread : Thread - 4 :: Looping Job No : 6
Thread : Thread - 4 :: Looping Job No : 7
Thread : Thread - 4 :: Looping Job No : 8
Thread : Thread - 4 :: Looping Job No : 9
Thread : Thread - 5 :: Looping Job No : 1
Thread : Thread - 5 :: Looping Job No : 2
Thread : Thread - 5 :: Looping Job No : 3
Thread : Thread - 5 :: Looping Job No : 4
Thread : Thread - 5 :: Looping Job No : 5
Thread : Thread - 5 :: Looping Job No : 6
Thread : Thread - 5 :: Looping Job No : 7
Thread : Thread - 5 :: Looping Job No : 8
Thread : Thread - 5 :: Looping Job No : 9
Thread : Thread - 3 :: Looping Job No : 0
Thread : Thread - 9 :: Looping Job No : 0
Thread : Thread - 9 :: Looping Job No : 1
Thread : Thread - 9 :: Looping Job No : 2
Thread : Thread - 9 :: Looping Job No : 3
Thread : Thread - 9 :: Looping Job No : 4
Thread : Thread - 9 :: Looping Job No : 5
Thread : Thread - 9 :: Looping Job No : 6
Thread : Thread - 9 :: Looping Job No : 7
Thread : Thread - 8 :: Looping Job No : 0
Thread : Thread - 9 :: Looping Job No : 8
Thread : Thread - 3 :: Looping Job No : 1
Thread : Thread - 9 :: Looping Job No : 9
Thread : Thread - 8 :: Looping Job No : 1
Future value: Thread - 9
Thread : Thread - 3 :: Looping Job No : 2
Thread : Thread - 3 :: Looping Job No : 3
Thread : Thread - 3 :: Looping Job No : 4
Thread : Thread - 3 :: Looping Job No : 5
Thread : Thread - 3 :: Looping Job No : 6
Thread : Thread - 3 :: Looping Job No : 7
Thread : Thread - 3 :: Looping Job No : 8
Thread : Thread - 3 :: Looping Job No : 9
Thread : Thread - 8 :: Looping Job No : 2
Thread : Thread - 8 :: Looping Job No : 3
Thread : Thread - 8 :: Looping Job No : 4
Thread : Thread - 8 :: Looping Job No : 5
Thread : Thread - 8 :: Looping Job No : 6
Thread : Thread - 8 :: Looping Job No : 7
Thread : Thread - 8 :: Looping Job No : 8
Thread : Thread - 8 :: Looping Job No : 9

ExecutorService extends Executor to provides method to manage thread termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks. The method submit extends Executor.execute(java.lang.Runnable) to create and return a Future. Methods invokeAny and invokeAll perform the most commonly useful forms of bulk execution, executing a collection of tasks and then waiting for at least one, or all, to complete. For an overview of Executors, visit Java 5 Executors.

0 comments:

Post a Comment