【四】线程池Executor(一)

线程池一类下的主要结构为


                      

Executor//execute(Runnable):用于执行此线程。

ExecutorService//    定义了更丰富的功能,例如关闭线程池,执行线程返回结果等等【submit、invokeAll、invokeAny】

AbstractExecutorService//抽象类,对一些方法提供了默认实现。该类实现了ExecutorService中的一些核心方法。例如submit、invokeAll、invokeAny。


submit(Runnable task):生成一个任务类型和Future接口的RunnableFuture对象,随后再执行execute方法,再返回Future。

这里的execute方法在子类中实现。

submit还可支持Callable。

Callable和Runnable的区别在于Callable带有返回值。即Callable = Runnable+返回值。JAVA提供了一个RunnableAdapter将Runnable换成Callable类型。

AbstractExecutorService有三种submit实现。虽然表面上看上去传参类型均不一致,但是实际上均是传入了Callable类型。传入的Runnable会通过newTaskFor方法将其转换成Callable:

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);//封装成FutureTask对象
}

public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);//
    this.state = NEW; // ensure visibility of callable
}

我们可以发现在submit方法中,其3种重载实现实际上均是传入了Callable类型。传入的Runnable会通过newTaskFor的方法将其转成Callable:在newTaskFor方法中,会通过Executors.callable方法,将传入的Runnable和result封装成Callable。这个方法中,将Runnable和Result包装成了一个RunnableAdapter。而这个RunnableAdapter实现了Callable接口,其中call方法便是执行了run方法,再返回result。


而除了submit方法之外,还有invokeAll

invokeAll较简单//大体就是将每个Callable先生成得到一个RunnableFuture。然后再循环execute执行每个任务。随后循环判断每个Future的get方法是否isDone,最后再返回Future的list。这个方法如果存在某一个task没有完成,例如出现异常等等,则会取消任务的execute。//future.cancel(ture)


invokeAny

其难点在于只要一个任务成功就要返回,并且取消其他任务。即重点在于找到第一个执行完毕的任务,使用的是LikedBlockingQueue。在源码中,使用到了一个ExecutorCompletionService用于执行任务,该Service内部封装的是一个Executor和一个LinkedBlockingQueue<Future>。在源码中,会先提交一个任务。随后尝试获取有没有执行结果,如若没有,并且还有任务未执行,则继续提交任务。随后如若没有任务在执行,但是还是没有结果,则退出循环。如若设置了超时,则等待相应时间。然如若未设置超时,且任务均已被提交,则一直等到第一个执行结果出来,如若存在了返回结果,则尝试获取结果,如若失败,则需等待下一个执行结果。

注:以上分析基于JDK8

贴上源码



 

综上便是AbstractExecutorService的相关方法的实现,接下来是其子类ThreadPoolExecutor。

猜你喜欢

转载自blog.csdn.net/qq_32302897/article/details/81076019