Sunday, 2 June 2019

Multithreading | Future and FutureTask in Java

Future
The Future interface provides methods to check if the computation is complete, to wait for its completion and to retrieve the results of the computation. The result is retrieved using Future’s get() method when the computation has completed, and it blocks until it is completed.

Future and FutureTask both are available in java.util.concurrent package from Java 1.5.

Prerequisite: Future and callable

FutureTask
FutureTask is a base concrete implementation of Future interface and provides asynchronous processing. It contains the methods to start and cancel a task and also methods that can return the state of the FutureTask as whether it’s completed or cancelled. We need a callable object to create a future task and then we can use Java Thread Pool Executor to process these asynchronously.

get() method of FutureTask acts like a latch as get() method waits or blocks till the task is completed. Once task completed, it returns the result or throws an ExecutionException. To avoid blocking, we can set the timeout in the get method.

package com.algorithmforum.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FutureTaskExample {

      public static void main(String[] args) {

            Callable callable1 = () -> {
                  Thread.sleep(1000);
                  return Thread.currentThread().getName();
            };

            Callable callable2 = () -> {
                  Thread.sleep(2000);
                  return Thread.currentThread().getName();
            };

            FutureTask futureTask1 = new FutureTask(callable1);
            FutureTask futureTask2 = new FutureTask(callable2);

            ExecutorService executor = Executors.newFixedThreadPool(2);
            executor.execute(futureTask1);
            executor.execute(futureTask2);

            while (true) {
                  try {
                        if (futureTask1.isDone() && futureTask2.isDone()) {
                              System.out.println("Done");
                              // shut down executor service
                              executor.shutdown();
                              return;
                        }

                        if (!futureTask1.isDone()) {
                              // wait indefinitely for future task to complete
                              System.out.println("FutureTask1 output=" + futureTask1.get());
                        }

                        System.out.println("Waiting for FutureTask2 to complete");

                        // Setting timeout 300 millis.
                        String s = futureTask2.get(300L, TimeUnit.MILLISECONDS);
                        if (s != null) {
                              System.out.println("FutureTask2 output=" + s);
                        }
                  } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                  } catch (TimeoutException e) {
                        System.err.println("Timeout");
                  }
            }
      }
}
Output
FutureTask1 output=pool-1-thread-1
Waiting for FutureTask2 to complete
Waiting for FutureTask2 to complete
Timeout
Timeout
Waiting for FutureTask2 to complete
Timeout
Waiting for FutureTask2 to complete
FutureTask2 output=pool-1-thread-2
Done

In the output of the above program, we can notice that it doesn’t print anything for sometimes because get() method of FutureTask waits for the task to get completed and then returns the output object. We have used overloaded method to wait for the specified amount of time only for futureTask2. Also, notice the use of isDone() method to make sure the program gets terminated once all the tasks are executed.

As such there is no benefit of FutureTask but it comes handy when we want to override some of the Future interface methods and don’t want to implement every method of Future interface.

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...