How it works...

This recipe focuses on asynchronous tasks that output a certain object such as an Employee, Department, ArrayList<Employee>, or ArrayList<Department>. Between the two, the Future<T> has been exposing methods to their invokers since Java 1.5 introduced concepts of concurrency. It has been used in wrapping tasks and its results whenever asynchronous methods returns any objects to their caller. Its implementation handler object called AsyncResult<T> is the one involved in wrapping beans, collections, or arrays of objects.

Since these objects are for non-blocking transactions, the AsyncResult<T> can be monitored and managed using the utility methods of Future<T>, namely the isCancelled(), isDone(), and get(). Since there are chances that the result will be void, we need to create a while loop to check if the task running inside AsyncResult<T> is still on process. Once isDone() returns true, we can retrieve the result through the get() method. Also, the isCancelled() can be called to monitor if the task has been cancelled by an internal background process. Study updateRecord() for the snippet on how to use these methods.

Whenever we have asynchronous services that return Callable<T>, the java.util.concurrent.Executors can help manage and execute the Callable<T> to extract Future<T>. In updateRecord() of DepartmentController, the non-blocking departmentServiceImpl.getDeptId(id) returns a Callable<Employee> for processing. To capture the result, the @Controller has to generate a new thread pool through Executor. In order to execute the Callable<Employee> task, the thread pool will execute the task at the background using its submit(), method which will eventually extract the Future<Employee>. Using all the Future<Employee> methods, the Employee object can be extracted successfully.

The real problem with using Future<T> as container object for tasks is the lack of callback implementation. Aside from Thread.sleep(), it lacks the synchronization technique to establish a well-managed sequence of cooperating or competing threads.

Thus, Java 1.8 and above has created an implementation of Future, the CompletableFuture<T>, that provides callbacks and extended features on asynchronous executions of tasks using its then methods with exception handling. Its utility methods support both blocking and non-blocking task executions. And most of all, CompletatableFuture<T> recognizes @FunctionalInterface and lambda expressions. In readEmployees() of EmployeeService, a Supplier<List<Employee>> has been generated to be executed by CompletableFuture< List<Employee>> in a common ForkJoinPool through its supplyAsync() method. This method also returns CompletableFuture<T> to the invoker. Another way of passing this container to the invoker is through its utility static method, CompletableFuture.completedFuture().

Although this recipe focused much on its blocking get() overloads, CompletableFuture<T> offers other asynchronous ways of retrieving its result such as thenAccept() which accepts a Consumer<T> to process the result. An example is updateRecordSubmit() request handler of ReportController.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.176.99