Executor相关类之AbstractExecutorService

该篇主要介绍Excecutor相关实现类的用法。

Executor相关类图

Executor相关实现类

Executor接口:里面只提供了一个方法 void execute(Runnable command);执行一个Runnable线程


ExecutorService内部方法

ExecutorService:提供Executor的管理(提交,停止运行)及查询,以及新增了invokeAll,invokeAny方法。


AbstractExecutorService:对ExecutorService的部分实现,以及新增了newTaskFor方法,该方法主要对Runnable以及Callable进行封装返回RunnableFuture。方便对submit方法提及的任务结果进行统一获取。

invokeAll方法实现如下

invokeAll方法

首先遍历集合内所有Callable,调用newTaskFor方法将返回结果放入ArrayList中,并执行task;

然后对list中task进行遍历获取每个task的结果;

最后finally对通过集合内所有任务执行完成与否进行判断,如果出现异常或者运行期间被取消,则对所有任务执行cancel操作。


invokeAll超时方法

超时方法逻辑总体没有变化,只是在执行任务期间添加了超时判断

1.在对list遍历期间,如果超时则直接返回futures,需要注意的是,此时可能并非左右任务都被execute.也就是说只是在单位时间内尽可能多的执行任务,并不保证所有任务都被执行。

2.在所有任务都执行后通过遍历futures进行Future.get方法是加了超时参数。


invokeAny

由图可知invokeAny方法最终是通过内部方法doInvokeAny执行的

doInvokeAny_1
doInvokeAny_2

通过代码可以看出该方法多出一个ExecutorCompletionService类,任务也是通过该类来进行提交。该类的主要作用是将执行的任务结果放入queue中方便进行获取。

总体流程如下:

1.首先在将tasks任务集合中的一个任务进行ecs.submit并放入futures集合中,激活任务数active=1

2.通过死循环获取第一个执行完的任务

        a.首先通过ecs.poll查看第一个提交的任务是否执行完毕

        b.当f == null时,首先判断ntasks>0如果是,则增加一个新任务执行,并更新ntasks和avtive,如果否,说明所有任务都正在运行,然后进行其他判断,当active==0时,说明所有任务都执行异常直接break,然后抛出异常信息;否则判断是否有执行超时时间限制,如果有则信息超时获取任务结果。当超时未获取到执行结果时抛出超时异常;否则则阻塞等待执行结果;

         c.如果执行f != null,则说明执行完毕,--active,进行f.get()获取,正常情况下获取成功,跳出循环,当获取异常时进行异常赋值并执行下一轮轮循环。

        d.finally中对所有任务进行取消

可以看出获取最先执行完的结果主要通过ExecutorCompletionService对task进行包装执行,下面查看该类是如何包装的


ExecutorCompletionService_1


ExecutorCompletionService_2


ExecutorCompletionService_3

通过代码看出该类对所有提交的task进行包装为QueueingFuture任务执行,QueueingFuture继承FutureTask并对其中的done方法进行了实现,将任务的结果放入BlockingQueue中。这就是为什么可以从队列中获取到任务执行结果的原因。也是invokeAny的核心思想所在。看完以后只能说构思巧妙,只能说大师的代码结构真牛皮。

你可能感兴趣的:(Executor相关类之AbstractExecutorService)