目 录
1 序言
2 基本概念
2.1 Runnable 和 Callable的区别
2.2 Future 和 FutureTask
2.3 ExecutorService中Future的应用
2.4 Future submit(Runnable task)
2.5 Future submit(Callable task)
2.6 ExecutorService中execute()在ThreadPoolExecutor中实现如下:
3 Future,RunnableFuture,FutureTask 关系
4 总结
参考文献
本文针对多线程中使用的几种任务:Runnable、Callable、RunnableFuture,FutureTask等进行详细介绍
Runnable和Callable都是定义了接口,可以用在线程池中异步执行,区别是:
Future是一个接口,主要是线程池中任务执行之后用于返回结果的获取,定义了
Future有一个直接继承接口RunnableFuture,RunnableFuture有一个实现的子类FutureTask,RunnableFuture这个接口同时还继承了Runnable接口,这意味着FutureTask可以作为Future或者Runnable使用。
再来看一下FutureTask的实现,最终内部保存了一个Callable对象,也就是提交的任务
先看构造函数
一共2个构造函数,一个是接受Callable,一个是接受Runnable和默认返回值。
详细看一下第二个构造参数,注释很清楚的说明,当你需要runnable可取消同时不关心返回值时,可以这样构建
上面两个函数将一个Runnable适配成了一个Callable,是Executors中提供的静态方法。
再看一下FutureTask对Runnable的实现
抛开其他的判断条件,其实就是对内部保存的Callable调用了call方法,进行执行并保存结果。这就是FutureTask主要的几个方法,下面有用。
上面2点主要是为了给这点做伏笔,现在我们来看为什么ExecutorService中的submit()既可以提交Runnable又可以提交Callable并返回结果,同时看看直接execute() Runnable会有什么不同。
先来看一下这个方法的实现
代码上可以很直观的看到,提交的Runnable被newTaskFor()适配成了RunnableFuture。来看一下newTaskFor()这个方法的实现。
复制代码
直接是new了一个FutureTask对象,上面我们分析过这种情况,runnable其实是会被适配成一个Callable的。
再来看一下这个方法
复制代码
跟上面的代码简直一摸一样,都是适配成了RunnableFuture。
看到这里可以明白,提交Runnable时是将Runnable适配成了Callable,也就是submit方法最终都会调用的的是Callable对象。
上面我们说过RunnableFuture实现了Runnable接口,当他被execute时,肯定是被当作Runnable使用的,看一下两个submit方法最终都是通过execute来执行的。
上面介绍FutureTask时我们知道,对Runnable的实现FutureTask最后调用的是Callable的call方法。
到这里可以知道了,
上面注释的意思是:
这个就是任务具体执行的过程
再来看构造方法,有两个构造方法如下
主要讲了几个概念Runnable、Callable、Future,RunnableFuture,FutureTask 以及相关的子类,总结如下:
https://juejin.cn/post/6844903672736907272
https://blog.csdn.net/weixin_34244102/article/details/87973014
https://blog.csdn.net/sageyin/article/details/116035166