FutureTask of Multithreading and Concurrency Series

Overview

In order to obtain the return result of the asynchronous thread, JDK1.5 was introduced.

Callable

Before introducing the Callable interface, we must mention the Runnable interface. The Runnable interface is an abstract interface that represents the business code of a thread in Java multithreading. But there is a problem: the run method has no return value and cannot be used in application scenarios that require a return value.
Source code:

@FunctionalInterface
public interface Callable<V> {
    
    
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Callable is a functional generic interface. Its only abstract method call has a return value, and the return value type is the actual type of the generic parameter. There is an exception statement that allows exceptions inside the method to not be caught.

Contrast: the Callable interface instance cannot be used as the target of the Thread thread instance; the Runnable interface instance can be used as the target construction parameter of the Thread thread instance to start a Thread thread.

The thread type in Java has only one Thread class and no other types. If the Callable instance needs to be executed asynchronously, it is necessary to find a way to assign a value to the target member of the Thread, a member of the Runnable type. To this end, Java provides a class that bridges the Callable instance and the target member of Thread-the FutureTask class.

Future

The Future interface mainly provides three functions such as the execution of concurrent tasks and obtaining the results:

  1. Judge whether the concurrent task is completed
  2. Get the result of the completion of concurrent tasks
  3. Cancel tasks in concurrent execution

Source code:

public interface Future<V> {
    
    
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Method description:

  • V get(): Obtain the result of concurrent task execution, obstructive. If the execution of the concurrent task is not completed, the thread that calls this method will be blocked until the execution of the concurrent task is completed
  • V get(Long timeout, TimeUnit unit): Get the result of concurrent task execution, blocking, but there is a blocking time limit, if the blocking time exceeds the set timeout time, this method will throw an exception
  • boolean isDone(): Get the execution status of concurrent tasks. Return true when task execution ends
  • boolean isCancelled(): Get the cancellation status of concurrent tasks. Return true if the task is cancelled before completion
  • boolean cancel(boolean mayInterruptRunning): Cancel the execution of concurrent tasks

FutureTask

The parameter of the constructor is the Callable type, which is actually a secondary encapsulation of the Callable type and can execute the call method of the Callable. Indirectly inherit the Runnable interface, which can be used as the target execution target of the Thread instance. A Callable instance is encapsulated internally, and then itself serves as the target of the Thread thread.

Externally, how to obtain the asynchronous execution result of the Callable instance is not to call its call method, but to obtain it through the corresponding method of the FutureTask class.

Based on the Synchronizer built by AQS, FutureTask is both Future, Runnable, and packaging Callable (if Runnable will eventually be converted to Callable), it is a combination of the two.

Constructor

The callable instance attribute must be initialized when the instance of the FutureTask class is constructed. Secondly, there is a run method inside FutureTask. The run method is an abstract method of the Runnable interface, which provides its own implementation inside the FutureTask class. When the Thread thread instance is executed, the run method will be used as the target to execute asynchronously. In the run implementation code inside FutureTask, the call method of its callable member will be executed. After the execution is complete, save the result.

State definition

private static final int NEW          = 0;
private static final int COMPLETING   = 1;
private static final int NORMAL       = 2;
private static final int EXCEPTIONAL  = 3;
private static final int CANCELLED    = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED  = 6;

In FutureTask, there are a total of the above 7 states, among which New is the initialization state of the instance, Completing and Interrupting are the intermediate states, and the remaining four are the final states.

  1. New->Completing->Normal
  2. New->Completing->Exceptional
  3. New->Cancelled
  4. New->Interrupting->Interrupted

Member variables

    private Callable<V> callable;
    private Object outcome; // non-volatile, protected by state reads/writes
    private volatile Thread runner;
    private volatile WaitNode waiters;
  1. There is a member of Callable type, which represents the logic of asynchronous execution
  2. The outcome attribute is used to save the result and can be obtained by the result obtaining method (such as get) of the FutureTask class

When obtaining asynchronous results through the get method of the FutureTask class, the main thread will also be blocked. This is the same as join, which is asynchronous blocking mode.

reference

Guess you like

Origin blog.csdn.net/lonelymanontheway/article/details/106035550