Java并发编程学习笔记10

69 阅读2分钟

携带结果的任务Callable与Future

Callable

类似于 Runnable 接口,但它可以返回任何对象并能够抛出异常。

Future

Java Callable 任务返回 java.util.concurrent.Future 对象。使用 Java Future 对象,我们可以找出 Callable 任务的状态并获得返回的对象。它提供了 get() 方法,可以等待 Callable 完成然后返回结果。 Java Future 提供了 cancel() 方法来取消关联的 Callable 任务。有一个重载版本的 get() 方法,我们可以在其中指定等待结果的时间,这有助于避免当前线程长时间阻塞。有 isDone() 和 isCancelled() 方法可以找出关联的 Callable 任务的当前状态。

Future 规范中隐含的是任务生命周期只能向前移动,不能向后移动。

将 Runnable 或 Callable 提交给 Executor 构成了从提交线程到执行任务的线程的安全发布。类似地,为 Future 设置结果值构成了从计算它的线程到通过 get 检索结果的任何线程的的安全发布。

CompletionService

一种将新异步任务的生成与已完成任务结果的使用分离开来的服务。生产者提交任务执行。消费者接受已完成的任务并按照他们完成的顺序处理他们的结果。

CompletionService 结合了 Executor 和 BlockingQueue 的功能。

假设我们要向线程池提交一批任务,并获取任务结果。一般的方式是提交任务后,从线程池得到一批 Future 对象集合,然后依次调用其 get() 方法。

这里有个问题:因为我们会要按固定的顺序来遍历 Future 元素,而 get() 方法又是阻塞的,因此如果某个 Future 对象执行时间太长,会使得我们的遍历过程阻塞在该元素上,无法及时从后面早已完成的 Future 当中取得结果。

有了 CompletionService,你不需要再持有 Future 集合。如果要得到最早的执行结果,只需要像下面这样:

String result = completionService.take().get();

这个 take() 方法返回的是最早完成的任务的结果,这个就解决了一个任务被另一个任务阻塞的问题。

为任务设置时间限制

Future.get 的定时版本支持此要求:它会在结果准备好后立即返回,但如果结果在超时期限内未准备好,则抛出 TimeoutException。