In this chapter, you learned the different mechanisms that you can use to work with tasks that return a result. These tasks are based on the Callable
interface, which declares the call()
method. This is a parameterized interface with the class returned by the call
method.
When you execute a Callable
task in an executor, you will always obtain an implementation of the Future
interface. You can use this object to cancel the execution of the task, know if the task has finished its execution or get the result returned by the call()
method.
You send Callable
tasks to the executor using three different methods. With the submit()
method, you send one task, and you will get immediately a Future
object associated with this task. With the invokeAll()
method, you send a list of tasks and will get a list of Future
objects when all the tasks have finished its execution. With the invokeAny()
method, you send a list of tasks, and you will receive the result (not a Future
object) of the first task that finishes without throwing an exception. The rest of the tasks are canceled.
The Java concurrency API provides another mechanism to work with these kind of tasks. This mechanism is defined in the CompletionService
interface and implemented in the ExecutorCompletionService
class. This mechanism allows you to decouple the execution of tasks and the processing of their results. The CompletionService
interface works internally with an executor and provides the submit()
method to send tasks to the CompletionService
interface and the poll()
and take()
methods to get the results of the tasks. These results are provided in the same order in which tasks finish their execution.
You also learned to implement these concepts with two real-world examples:
In the next chapter, you will learn how to execute algorithms in a concurrent way that can be divided into phases, for example, a keyword extraction algorithm. You can implement that algorithm in the following three steps:
The main characteristic of these steps is that you must finish one completely before you can start the next one. Java concurrency API provides the Phaser
class to facilitate the concurrent implementation of these algorithms. It allows you to synchronize all the tasks involved on it at the end of a phase, so none of them will start the next one until all have finished the current one.
18.188.65.241