Future, A Token of Task Submission
Let's discuss what is Future and how is it used for monitoring a task.
Join the DZone community and get the full member experience.Join For Free
Future, A Token of Task Submission
I believe, the title is very abstract but clearly explains the purpose. The concurrency package is the boss when it's come to asynchronous programming. Of course, this is the continuation of my previous articles on asynchronous programming.
We have seen creating Threads and make use of Executor Framework for the Thread management. Also, We look at how to submit a task and how is it processed internally in the executor. But we haven't seen how to check the status or getting the result etc.
That's the purpose that brought us the Future Interface. Future lies in the same package as other concurrency class that is
java.util.concurrent. And It's available since Java 1.5.
In simple words, a Future is a token of task creation and comes with various methods to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.
I think It's enough about the introduction and let's get our hands dirty.
This is the skeleton of the Future interface. We will go in order create->status->get->cancel.
Create a Future
The future can be obtained simply by submitting a task to an ExecutorService. Here, I'm creating a component and initializing an ExecutorService with available core capacity.
Future is a Generic interface. Generic type represents the Type of the return data. Let's understand it with Callable that returns an integer value.
Here, We have created a callable task that returns the integer value. The return type of callable is Integer, and so the generic type of the Future obtained by the submission of the callable task is also Integer.
Now you might be thinking, callable returns the value, but the Runnable does not return a value, so what will be the type of Future that is obtained by the Runnable submission.
Here we don't know the return type, so the executor returns Future<?>.
We have our task submitted and our Future is in hand. Is the task finished?
Future.isDone() provides the status of the task. Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation — in all of these cases, this method will return true.
Future.get() is an important method. Of course, It's used for getting the result, but the purpose is more beyond it.
If you have the runnable task and you just want to check the status of completion with
isDone() and not call the
get(), because the task does not return the data. It's okay until your task completes successfully.
If your task completes exceptionally then the exception is stored in the Future reference only. The only way to get it is
Let's modify our
submitRunnable so that it produces an unhandled exception.
And now I'm calling the
With no exceptions, It will complete smoothly. Until we call
future.get(), we don't see a trace of Arithmetic Exception. It will be a mystery!
Now you know the importance of
Future.get(), Let's see how to use it.
Future.get() throws 3 exceptions basically.
InterruptedException— In case the task is interrupted
ExecutionException— In case the task is completed exceptionally where you get the exceptions that occurred in the task.
CancellationException— In case the task is canceled and you try to call the
get(). This extends the RuntimeException (unchecked exception). So it doesn't complain about catching it.
Future.get() With Waiting Period
Future.get() comes with an overloaded method, that takes timeout and TimeUnit:
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
Now it throws an additional exception,
Future.cancel (boolean mayInterruptIfRunning)
As per Docs,
Attempts to cancel the execution of this task. This attempt will fail if the task has already completed, has already been canceled, or could not be canceled for some other reason.
If successful, and this task has not started when cancel is called, this task should never run.
If the task has already started, then the
mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
Returns true if this task was canceled before it completed normally.
Handling Task Cancellation Programmatically
My opinion on cancel: there are certain cases in which a task cannot be canceled at all. It's better to handle cancelation programmatically.
That's all from me about the Future interface. I hope, you enjoyed the article. See you again with another article on CompletableFuture.
Opinions expressed by DZone contributors are their own.