preface

There are two ways to create threads: one is to inherit threads directly, and the other is to implement the Runnable interface. One drawback of both approaches is that you can’t get the results of the execution after the task is completed. If you want to get results, you have to share variables or use thread communication to get results, which can be cumbersome to use. Since Java 1.5, Callable and Future have been available to get the result of a task’s execution after it has finished

Introduction to Callable

The Callable interface represents a piece of code that can be called and return results; The Future interface represents asynchronous tasks that are Future results of tasks that have not yet been completed. So Callable is used to produce results and Future is used to get results.

The Callable interface uses generics to define its return type. The Executors class provides some useful methods for executing tasks in the Callable thread pool. Since the Callable task is parallel (parallel is when the whole thing looks parallel, but only one thread is executing at any point in time), we have to wait for the result it returns. Java. Util. Concurrent. The Future object to solve the problem for us. A Future object is returned after a Callable task is submitted by the thread pool. It can be used to know the status of the Callable task and get the execution result returned by the Callable. The Future provides a get() method that lets us wait for the Callable to end and get its execution result.

2 the Future to introduce

2.1 There are five methods declared in the Future interface. The functions of each method are explained as follows:
methods role
cance(boolean mayInterruptIfRunning) If the parameter is true, the task in progress is interrupted. Otherwise, true is returned when the task is cancelled successfully. Otherwise, false is returned
isCancelled() Method indicates whether the task was cancelled successfully, or returns true if the task was cancelled successfully before it completed normally.
isDone() Method indicates whether the task has completed, and returns true if it has;
get() Method is used to get the result of the execution. This method blocks and does not return until the task is completed.
get(long timeout, TimeUnit unit) Sets the return time of the calculation result and throws a TimeOutException if the calculation result is not returned within the specified time.
2.2 Future provides three functions:

1) Judge whether the task is completed; 2) Can interrupt the task; 3) Can obtain the task execution results. Because a Future is just an interface, it cannot be used directly to create objects, hence the following FutureTask.

3 FutureTask

Let’s first look at the implementation of FutureTask:


public class FutureTask<V> implements RunnableFuture<V>
Copy the code

The FutureTask class implements the RunnableFuture interface. Let’s look at the implementation of the RunnableFuture interface:


public interface RunnableFuture<V> extends Runnable.Future<V> {
    void run(a);
}
Copy the code

As you can see, RunnableFuture inherits the Runnable and Future interfaces, while FutureTask implements the RunnableFuture interface. So it can either be executed by the thread as a Runnable, or it can be used as a Future to get the return value of a Callable.

FutureTask provides two constructors:


public FutureTask(Callable<V> callable) {}public FutureTask(Runnable runnable, V result) {}Copy the code

In fact, FutureTask is a unique implementation class for the Future interface.

4 Use of Future and FutureTask

4.1 Using Callable+Future to Obtain the Execution Result

public class CallableFutureTest {


    public static void main(String[] args) {
        // Create a thread pool
        ExecutorService es = Executors.newSingleThreadExecutor();
        // Create a Callable object task
        CallableDemo calTask = new CallableDemo();
        // Submit the task and get the execution result
        Future<Integer> future = es.submit(calTask);
        // Close the thread pool
        es.shutdown();
        try {
            Thread.sleep(2000);
            System.out.println("Main thread is performing other tasks.");

            if(future.get() ! =null) {
                // Output the obtained results
                System.out.println("future.get()-->" + future.get());
            } else {
                // Output the obtained results
                System.out.println("Future.get () did not get result"); }}catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Main thread executing complete"); }}class CallableDemo implements Callable<Integer> {

    private int sum;

    @Override
    public Integer call(a) throws Exception {
        System.out.println("The Callable child thread has started calculating!");
        Thread.sleep(2000);

        for (int i = 0; i < 100; i++) {
            sum = sum + i;
        }
        System.out.println("The Callable child thread is finished counting!");
        returnsum; }}Copy the code

The Callable child thread has started calculating! The Callable child thread has finished counting! Future.get ()-->4950 The main thread is executingCopy the code
4.2 Using Callable+Future to Obtain the Execution result

public class CallableFutureTest {


    public static void main(String[] args) {
// // Create a thread pool
// ExecutorService es = Executors.newSingleThreadExecutor();
// // Create a Callable object task
// CallableDemo calTask=new CallableDemo();
// // Submit a task and obtain the execution result
// Future
      
        future =es.submit(calTask);
      
// // Closes the thread pool
// es.shutdown();

        // Create a thread pool
        ExecutorService es = Executors.newSingleThreadExecutor();
        // Create a Callable object task
        CallableDemo calTask = new CallableDemo();
        / / create FutureTask
        FutureTask<Integer> futureTask = new FutureTask<>(calTask);
        // Execute the task
        es.submit(futureTask);
        // Close the thread pool
        es.shutdown();
        try {
            Thread.sleep(2000);
            System.out.println("Main thread is performing other tasks.");

            if(futureTask.get() ! =null) {
                // Output the obtained results
                System.out.println("futureTask.get()-->" + futureTask.get());
            } else {
                // Output the obtained results
                System.out.println("Futuretask.get () did not get result"); }}catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("Main thread executing complete"); }}class CallableDemo implements Callable<Integer> {

    private int sum;

    @Override
    public Integer call(a) throws Exception {
        System.out.println("The Callable child thread has started calculating!");
        Thread.sleep(2000);

        for (int i = 0; i < 100; i++) {
            sum = sum + i;
        }
        System.out.println("The Callable child thread is finished counting!");
        returnsum; }}Copy the code

The Callable child thread has started calculating! The Callable child thread has finished counting! Futuretask.get ()-->4950 The main thread is executing successfullyCopy the code

But the two approaches are ultimately the same: the first approach, Callable+Future, is ultimately implemented as Callable+FutureTask. Future Future = executor.submit(task); Let’s look at the source code for executor.submit(task) :


. / / Java. Util. Concurrent AbstractExecutorService class
   / * * *@throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc} * /
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);Submit (Callable
      
        task) creates a RunnableFuture
       
         interface implementation class
       
      
        execute(ftask);
        return ftask;
    }
Copy the code

FutureTask is an implementation of RunnableFuture, so let’s see what newTaskFor(Callable Callable) does:


 protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }
Copy the code

For more Android knowledge, please click on the card below.