Java ~ Executor ~ CompletionService【总结】

前言


 文章

  • 相关系列:《Java ~ Executor【目录】》(持续更新)
  • 相关系列:《Java ~ Executor ~ CompletionService【源码】》(学习过程/多有漏误/仅作参考/不再更新)
  • 相关系列:《Java ~ Executor ~ CompletionService【总结】》(学习总结/最新最准/持续更新)
  • 相关系列:《Java ~ Executor ~ CompletionService【问题】》(学习解答/持续更新)
  • 涉及内容:《Java ~ Executor【总结】》
  • 涉及内容:《Java ~ Executor ~ Callable【总结】》
  • 涉及内容:《Java ~ Executor ~ Future【总结】》
  • 涉及内容:《Java ~ Executor ~ ExecutorCompletionService【总结】》
  • 涉及内容:《Java ~ Thread ~ Runnable【总结】》

一 概述


 简介

    任务的“生产”与“消费”默认是同步的。在正式讲述CompletionService(完成服务)接口的作用之前我们需要先了解所谓任务的“生产”与“消费”是什么概念。在Executor(执行器)框架中任务的“生产”指任务向执行器递交的行为,而“消费”则指将任务从执行器中移除的行为,即执行器不再持有任务的引用,因此“消费”只能在任务执行结束后(完成/异常/取消)后发生。任务的“生产”与“消费”通常被认为是同步的,这是一个会让初学者非常疑惑的点,因为基于大多数执行器接口实现类都采用异步执行方案的原因,并无法保证递交方法会在任务“消费”后返回,因此同步就显得毫无道理。那为什么还会有同步的说法呢?这是因为递交方法同步返回的Future(未来)拥有追踪任务执行状态的能力。因此即使任务被执行器异步执行,也可在需要时通过调用未来的get()方法达到同步“消费”(并获取执行结果/异常)的目的,其效果与任务在递交时即被同步“消费”是等价的,因此任务的“生产”与“消费”本质是一种间接/变相的同步。

    同步“消费”的前提是确定具体需要被“消费”的任务。想要进行同步“消费”就必须先确定具体需要被“消费”的任务,这其中原因是因为我们需要调用该任务关联未来的get()方法。这并没有想象中简单,因为递交返回的未来未必是我们想要的目标未来,即递交的任务未必是我们想“消费”的任务。典型的例子是:如何获取一组递交任务中最早执行结束(完成/异常/取消)任务的结果呢?事实上开发者应该很清楚该问题在使用同步“消费”的情况下是无法/很难解决的,因为无法得知哪个同步未来的代表任务会最早执行结束(完成/异常/取消)。因此在包含上述举例在内的某些场景中我们也希望“消费”可以是异步的,即不通过调用同步未来get()方法的方式来“消费”任务,以达到对任务“消费”的顺序/时间/条件等多项维度进行自定义的目的。

    完成服务接口在定义上提供将任务的“生产”与“消费”从概念上分离的能力。完成服务接口在递交方法的基础上额外定义了移除方法对递交至完成服务的任务进行“消费”(并返回相关的未来),使得任务的“生产”与“消费”之间失去了交集而由原本的同步关系转变为了异步关系。开发者可以通过实现移除方法的方式自定义异步“消费”的逻辑,例如可以按任务执行结束(完成/异常/取消)的顺序“消费”任务以实现上述举例中的需求,事实上完成服务接口唯一的实现类ExecutorCompletionService(执行器完成服务)也确实是如此实现的,该知识点会在相关文章中详述。为了实现获取一组递交任务中最早执行结束(完成/异常/取消)任务结果的需求,开发者需要在任务异步“消费”后调用异步未来的get()方法。此时的get()方法已不再具有同步“消费”的意义,只单纯的被用来获取异步“消费”任务的执行结果。

二 方法


 递交

  • Future submit(Callable task) —— 递交 —— 向当前完成服务递交指定可回调/任务,并返回可追踪/获取指定可回调/任务执行状态/结果/异常的未来,但不推荐使用该未来等待指定可回调/任务执行结束。

  • Future submit(Runnable task, V result) —— 递交 —— 向当前完成服务递交指定可运行/任务,并返回可追踪/获取指定可运行/任务执行状态/结果/异常的未来,但不推荐使用该未来等待指定可运行/任务执行结束。方法会同步传入用于承载指定可运行/任务执行结果/异常的变量,承载后指定可运行/任务执行结果/异常即可通过变量直接获取,也会向未来传递,因此该方法返回未来的get()方法可获取指定可运行/任务的执行结果/异常。

 移除

  • Future poll() —— 轮询 —— 从当前完成服务中移除并获取下个结束(完成/异常/取消)任务。该方法是移除方法“特殊值”形式的实现,当当前完成服务存在结束(完成/异常/取消)任务时移除并返回下个结束(完成/异常/取消)任务;否则返回null。

  • Future take() throws InterruptedException —— 拿取 —— 从当前完成服务中移除并获取下个结束(完成/异常/取消)任务。该方法是移除方法“阻塞”形式的实现,当当前完成服务存在结束(完成/异常/取消)任务时移除并返回下个结束(完成/异常/取消)任务;否则等待至存在结束(完成/异常/取消)任务为止。

  • Future poll(long timeout, TimeUnit unit) throws InterruptedException —— 轮询 —— 从当前完成服务中移除并获取下个结束(完成/异常/取消)任务。该方法是移除方法“超时”形式的实现,当当前完成服务存在结束(完成/异常/取消)任务时移除并返回下个结束(完成/异常/取消)任务;否则在指定等待时间内等待至存在结束(完成/异常/取消)任务为止,超出指定等待时间则返回null。

你可能感兴趣的:(Java,#,Executor,java,开发语言,Executor)