Future类有什么用
Future类是异步思想的典型应用,主要用在一些需要执行耗时任务的场景,避免程序一直原地等待耗时任务完成,执行效率太低。具体来说:**当我们执行某一个耗时的任务时,可以将这个耗时任务交给一个子线程去异步执行,同时我们可以干点其他事情,不用傻傻等待耗时任务执行完成,等我们的事情干完后,我们在通过Future类获取到耗时任务的执行结果**
。这样一来,程序的执行效率就明显提高了。
这其实就是多线程中经典的Future模式。核心思想是异步调用,主要用在多线程领域。
在Java中,Future类只是一个泛型接口,位于java.util.concurrent包下,其中定义了5个方法,主要包括下面四个功能:
- 取消任务 cancel(boolean mayInterruptIfRunning)
- 判断任务是否被取消 boolean isCancelled();
- 判断任务是否已经执行完成。boolean isDone();
- 获取任务执行结果。V get() 和 V get(long timeout, TimeUnit unit)。
简单理解就是:我有一个1. 任务,提交给Future处理
,2. 任务执行期间可以去做别的事情
,并且,在这3. 期间可以取消任务以及4. 获取任务的执行状态
。5. 一段时间之后,可以从Future那里直接获取任务执行结果
。
Callable和Future有什么关系
我们可以通过FutureTask来理解Callable和Future之间的关系。
FutureTask提供了Future接口的基本实现,常用来封装Callable和Runnable,具有取消任务、查看任务是否执行完成以及获取任务执行结果的方法。ExecutorService.submit()方法返回的其实就是Future的实现类FutureTask。
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
FutureTask不光实现了Future接口,还实现了Runnable接口,因此可以作为任务直接被线程执行。
FutureTask有两个构造函数,可传入Callable和Runnable对象。实际上,传入Runnable对象也会在方法内部转换为Callable对象。
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}
public FutureTask(Runnable runnable, V result) {
// 通过适配器RunnableAdapter来将Runnable对象runnable转换成Callable对象
this.callable = Executors.callable(runnable, result);
this.state = NEW;
}
FutureTask相当于对Callable进行了封装,管理着任务执行的情况,存储了Callable的call方法的任务执行结果。
CompletableFuture类有什么用
Future在实际使用过程中存在一些局限性比如不支持异步任务的编排组合、获取计算结果的get()方法为阻塞调用。
Java8引入CompletableFuture类可以解决Future的这些缺陷。CompletableFuture除了提供更为好用和强大的Future特性之外,还提供了函数式编程,异步任务编排组合(可以将多个异步任务串联起来,组成一个完整的链式调用)等能力。
CompletableFuture 类定义
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
}
可以看到,CompletableFuture同时实现了Future和CompletionStage接口。
CompletionStage接口描述了一个异步计算的阶段,很多计算可以分成多个阶段或步骤,此时可以通过她将所有步骤组合起来,形成异步计算的流水线。