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:
- Judge whether the concurrent task is completed
- Get the result of the completion of concurrent tasks
- 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 completedV 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 exceptionboolean isDone()
: Get the execution status of concurrent tasks. Return true when task execution endsboolean isCancelled()
: Get the cancellation status of concurrent tasks. Return true if the task is cancelled before completionboolean 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.
New->Completing->Normal
New->Completing->Exceptional
New->Cancelled
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;
- There is a member of Callable type, which represents the logic of asynchronous execution
- 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.