logo头像

From zero to HERO

Java 中的 Future 接口

本文于 1349 天之前发表,文中内容可能已经过时。

1. 前言

Java 1.5 提供了 java.util.concurrent.Future 接口,处理异步调用和并发处理时非常有用,今天我们来研究一下这个接口。在 JDK 中对 Future 是这么描述的:

A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.

大致意思就是: Future 是异步计算结果的容器接口,它提供了在等待异步计算完成时检查计算是否完成的状态,并在异步计算完成后获取计算结果而且只能通过 get 方法获取结果,如果异步计算没有完成则阻塞,当然你可以在异步计算完成前通过 cancel 方法取消,如果异步计算被取消则标记一个取消的状态。如果希望异步计算可以被取消而且不提供可用的计算结果,如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

2. 使用场景

Java 的多线程机制,在没有 Future 之前如果要保存多线程的计算结果,必须等待方法计算完,在此期间你只能等着,无论你的计算逻辑多么的耗时,这显然不合理。我们希望在处理高耗时的任务同时去干其它事情而不是等着,这就是 Future 被设计出来的原因。
从上面的说明我们可以知道 Future 用于处理比较耗时的异步计算任务,在结果计算出来之前会一直阻塞挂起除非被取消计算。利用这些特性大概的使用场景如下:

  • 高消耗的科学计算场景,比如深度学习中的张量计算。
  • 海量复杂结构数据处理(大数据处理)。
  • 异步大文件下载、异步爬虫爬取数据。
  • 其它一些高耗时、海量数据的异步 Web 服务。

3. Future

我们将来详细了解一下Future 提供的方法。

3.1 cancel

boolean cancel(boolean mayInterruptIfRunning) 调用该方法将试图取消对任务的执行。如果任务已经完成了、已取消、无法取消这种尝试会失败。 当该方法调用时任务还没有开始,方法调用成功而且任务将不会再执行。 如果任务已经启动,则 mayInterruptIfRunning 参数确定是否执行此任务的线程应该以试图停止任务被中断。此方法返回后调用isDone 方法将返回 true 。 后续调用 isCancelled 总是返回第一次调用的返回值。

3.2 isCancelled

boolean isCancelled() 如果任务在完成前被取消,将返回 true

请注意任务取消是一种主动的行为。

3.3 isDone

boolean isDone() 任务已经结束,在任务完成、任务取消、任务异常的情况下都返回 true

3.4 get

V get() throws InterruptedException, ExecutionException 调用此方法会在获取计算结果前等待。一但计算完毕将立刻返回结果。它还有一个重载方法 V get(long timeout, TimeUnit unit) 在单位时间内没有返回任务计算结果将超时,任务将立即结束。

4. 总结

本文介绍了如何 Java 解决异步任务获取结果的问题,Future 只是一个规定的范式,我们可以通过该范式实现耗时任务时充分利用计算资源来进行并行处理任务并在合适的时候获取任务的计算结果。基于篇幅的原因我们将在下一篇介绍关于 Future 的一个常用实现 FutureTask,多多关注。

评论系统未开启,无法评论!