获取任务的结果

获取任务的结果

Executor 框架使用 Runnable 作为其基本的任务表现形式。如果提交的任务是一次延迟计算且我们需要获取计算的结果,只通过 Runnable 是无法实现的。原因在于其 run 方法不能返回一个值或抛出一个受查异常。可以使用 Callable 或 Future 来实现。

如果向 Executor 提交一组计算任务,且希望在计算完成后获取结果,有两种方式:

  1. 保留与每个任务关联的 Future,然后反复使用 get 方法,同时将 timeout 参数指定为 0,从而实现轮询判断任务是否完成。
  2. 使用 CompletionService(完成服务)。
Callable

对于存在延迟的计算(数据库查询、网络资源下载),Callable 是一种更好的抽象,其主入口点 call 方法将返回一个值,并可以抛出一个异常,Executor 中包含一些方法可以将其它类型的任务封装成 Callable。

Future

Future 可以表示一个任务的生命周期,其提供了相应的生命周期方法来获取任务的状态、计算结果或者取消任务。Future 规范中任务的生命周期只能前进无法后退,当某个任务完成后将永远停留在 “完成” 状态上。

Future 的 get 方法可以获取计算结果:

  1. 如果任务已完成,get 将立即返回结果;
  2. 如果还未完成,get 将阻塞直到任务完成;
  3. 如果任务抛出了异常,get 将异常封装成 ExecutionException 并重新抛出,可以通过 getCause 来获得被封装的初始异常;
  4. 如果任务取消,get 将抛出 CancellationException。

有多种方法可以创建一个 Future 来描述任务:

  1. ExecutorService 中的所有 submit 方法都将返回一个 Future,从而将一个 Runnable 或 Callable 提交给 Executor 可以返回一个 Future 来获得任务的执行结果或取消任务。
  2. 可以显示地为某个指定的 Runnable 或 Callable 实例化一个 FutureTask。

ExecutorService 的实现可以改写 AbstractExecutorService 中的 newTaskFor 方法,从而根据已提交的 Runnable 或 Callable 来控制 Future 的实例化过程。

将 Runnable 或 Callable 提交到 Executor 的过程中,包含一个安全发布过程:将 Runnable 或 Callable 从提交线程发布到最终执行任务的线程。 类似的,设置 Future 结果的过程中也包含一个安全发布过程:将这个结果从计算它的线程发布到通过 get 方法获得它的线程。

CompletionService

CompletionService 将 Executor 和 BlockingQueue 融合在一起,可以将 Callable 任务提交给它,然后使用类似队列操作的 take 和 poll 方法获取已完成的结果,这些结果会在完成时被封装为 Future。

ExecutorCompletionService 实现了 CompletionService,并将计算部分委托给一个 Executor。

ExecutorCompletionService 的实现:

  1. 构造函数中创建一个 BlockingQueue 来保存计算完成的结果。
  2. 计算完成时,调用 FutureTask 的 done 方法。
  3. 提交某个任务时,将该任务包装为一个 QueueingFuture(FutureTask 的子类),改写子类的 done 方法,并将结果放入到 BlockingQueue 中。
  4. take 和 poll 方法委托给了 BlockingQueue,均为阻塞方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值