概述
为了获取异步线程的返回结果,JDK1.5引入。
Callable
在介绍Callable接口前,得提到Runnable接口。Runnable接口是在Java多线程中表示线程的业务代码的抽象接口。但有个问题:run方法没有返回值,不能用于需要有返回值的应用场景。
源码:
@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是一个函数式泛型接口,其唯一的抽象方法call有返回值,返回值的类型为泛型形参的实际类型。有一个异常声明,容许方法内部的异常不经过捕获。
对比:Callable接口的实例不能作为Thread线程实例的target来使用;而Runnable接口实例可以作为Thread线程实例的target构造参数,开启一个Thread线程。
Java中的线程类型,只有一个Thread类,没有其他的类型。如果Callable实例需要异步执行,就要想办法赋值给Thread的target成员,一个Runnable类型的成员。为此,Java提供在Callable实例和Thread的target成员之间一个搭桥的类——FutureTask类。
Future
Future接口主要提供对并发任务的执行及获取其结果等3大功能:
- 判断并发任务是否执行完成
- 获取并发的任务完成后的结果
- 取消并发执行中的任务
源码:
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;
}
方法说明:
V get()
:获取并发任务执行的结果,阻塞性的。如果并发任务没有执行完成,调用此方法的线程会一直阻塞,直到并发任务执行完成V get(Long timeout, TimeUnit unit)
:获取并发任务执行的结果,阻塞性,但有阻塞时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常boolean isDone()
:获取并发任务的执行状态。任务执行结束,则返回trueboolean isCancelled()
:获取并发任务的取消状态。任务完成前被取消,则返回trueboolean cancel(boolean mayInterruptRunning)
:取消并发任务的执行
FutureTask
其构造函数的参数为Callable类型,实际上是对Callable类型的二次封装,可以执行Callable的call方法。间接地继承Runnable接口,从而可以作为Thread实例的target执行目标。内部封装一个Callable实例,然后自身又作为Thread线程的target。
在外部,如何要获取Callable实例的异步执行结果,不是调用其call方法,而是需要通过FutureTask类的相应方法去获取。
基于AQS构建的Synchronizer,FutureTask既是Future、Runnable,又是包装Callable(如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。
构造函数
callable实例属性必须要在FutureTask类的实例构造时进行初始化。其次,FutureTask内部有一个run方法。这个run方法是Runnable接口的抽象方法,在FutureTask类的内部提供了自己的实现。在Thread线程实例执行时,会将这个run方法作为target目标去异步执行。在FutureTask内部的run实现代码中,会执行其callable成员的call方法。执行完成后,将结果保存起来。
状态定义
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;
FutureTask中,一共有上面7种状态,其中New为实例的初始化状态, Completing和Interrupting为中间状态,其余四个为最终状态。
New->Completing->Normal
New->Completing->Exceptional
New->Cancelled
New->Interrupting->Interrupted
成员变量
private Callable<V> callable;
private Object outcome; // non-volatile, protected by state reads/writes
private volatile Thread runner;
private volatile WaitNode waiters;
- 有一个Callable类型的成员,代表异步执行的逻辑
- outcome属性,用于保存结果,可供FutureTask类的结果获取方法(如get)来获取
通过FutureTask类的get方法获取异步结果时,主线程也会被阻塞的。这一点和join一样,都是异步阻塞模式。