Waiting for Results
How can developer know when a task submitted to an ExecutorService is complete ? As it was mentioned above, the submit() method returns a Future<V> object, that can be used to determine the result, for instance
Future<?> future = service.submit(() -> System.out.println("Hello"));
The Future class includes methods that are useful in determining the state of a task, see table
Method Name | Description |
boolean isDone() | Returns true if the task was completed, threw an exception, or was cancelled |
boolean isCancelled() | Returns true if the task was cancelled before it completed normally |
boolean cancel() | Attempts to cancel execution of the task |
V get() | Retrieves the result of a task, waiting endlessly if it is not yet available |
V get(long timeout, TimeUnit unit) | Retrieves the result of a task, waiting the specified amount of time. If the result is not ready by the time the timeout is reached, a checked TimeoutException will be thrown |
The following example shows the use of Future instance :
public class FutureExample {
private static int counter;
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService service = null;
try {
service = Executors.newSingleThreadExecutor();
Future<?> result = service.submit(() -> {
for (int i = 0; i < 500; i++) {
FutureExample.counter++;
try {
Thread.sleep(19);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
result.get(10, TimeUnit.SECONDS);
System.out.println("Reached!");
} catch (TimeoutException e) {
System.out.println("Not reached in time");
} finally {
if (service != null) {
service.shutdown();
}
}
}
}
This example uses Thread class, but not directly – but by turning to ExecutorService. This is the essence of Concurrency API: to do complex things with threads without using the Thread class directly. The code in example above also waits at most 10 seconds, following a TimeoutException if the task is not done.
TimeUnit is an enum type, and its values define the order of duration (TimeUnit.NANOSECONDS, TimeUnit.MICROSECONDS, … , TimeUnit.DAYS). It is widely used in Concurrency API. TimeUnit is helpful for using instead of Thread.sleep(int milliseconds) : TimeUnit.SECONDS.sleep(duration);
It is more clearly and easier to perceive.