![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173605135-200015639.png)
![Executor.jpg](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173607697-672254913.jpg)
要点总结
Executor表示的任务类型
主要有3种:
- Runnable: 无返回值,无异常抛出;
- Callable:有返回值,可以异常抛出;
- Future任务: 表示异步计算,可取消; 通过newTaskFor()方法,将Runnable/Callable任务转换为Future任务;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173608432-1631010458.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173608760-1747853183.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173609166-1246792133.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173609447-291890617.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173609729-598842866.png)
由上面可知: FutureTask既是Runnable任务,也是Future任务;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173610151-1694567567.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173610416-464581169.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173610635-434207410.png)
Future任务的创建方法
Future任务的特点:
- 异步计算:通过get()方法来获取异步计算的结果;
- 可取消;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173609166-1246792133.png)
创建Future任务
主要有2种方式:
- 通过FutureTask构造函数来创建;(事实上,FutureTask是Future接口的唯一实现)
- 通过ExecutorService的submit()方法来创建;
- 方式1:通过FutureTask的构造函数来创建;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173610885-639657970.png)
- 方式2:通过ExecutorService的submit()方法来创建;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173611151-285602745.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173611463-1545356100.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173611651-1898835214.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173611885-328622411.png)
由上面可知:ExecutorService.submit()最终还是使用FutureTask构造函数来创建Future任务;
Executor框架,任务提交的2种方式
- Executor接口:executor(Runnable command);
- ExecutorService.submit(xxx): 是对Executor接口提交任务的扩充;
- 方式1:
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173612166-1195567831.png)
- 方式2:
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173612385-522744025.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173612760-274443420.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173613041-216288774.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173613510-87330812.png)
ExecutorService接口
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173613963-209604187.png)
ExecutorService接口是对Executor接口的扩展,主要增加了如下方法:
- 生命周期管理方法;
- 提交任务的简便方法;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173614369-1647677033.png)
shutdown()和shutdownNow()比较
- shutdown():平缓关闭,不会接收新任务的提交,会等待已提交任务全部执行完;
- shutdownNow():粗暴关闭,不会接收新任务的提交,尝试取消正在运行的任务,返回已提交但尚未运行的任务列表;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173614838-593435229.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173615447-1202210674.png)
批量任务:invokeAll()/invokeAny()
方法说明
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173615932-1289844235.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173616322-1466661395.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173616744-1735578148.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173617229-778650925.png)
invokeAll()实现原理
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173617651-963725852.png)
CompletionService接口
具体实现类: ExecutorCompletionService
- 用于提交批量异步任务,并获取结果;
- 用于将批量异步任务的生产和消费进行解耦;
方法介绍
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173617994-1946304765.png)
使用示例
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173618291-1661036979.png)
实现原理
- Executor: ExecutorCompletionService委托Executor来执行任务提交操作;
- BlockingQueue: 委托BlockingQueue来保存计算结果;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173618494-1349502039.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173618744-271953118.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173619526-1404455943.png)
步骤1:提交任务
- 将提交的任务封装为QueueingFuture;
- 委托Executor进行任务提交;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173620229-1376939364.png)
步骤2: 重写done()方法
- 重写FutureTask的done()方法,当Future任务执行完成后,调用done(),将Future任务添加到BlockingQueue中;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173620838-647140617.png)
步骤3:
- 委托BlockingQueue实现获取任务的同步;
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173621135-742972171.png)
CompletionService接口和ExecutorService.invokeAll()比较
相同点:
都可以进行批量任务提交与处理;
不同点:
ExecutorService.invokeAll():
- 每次提交1组任务,返回时,也是返回1组任务(Future);
- 必须等待所有任务执行完,才会返回结果,返回的任务列表与提交的任务列表顺序相同;
CompletionService接口:
- 每次提交1个任务,任务执行完成后,会将任务放到BlockingQueue中;
- BlockingQueue中存放的任务顺序,与提交的任务顺序很可能不同,哪个任务先执行完,就先放入哪个任务;
- 不必等待所有任务执行完;
![ThreadPoolExecutor.png](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173622307-1894558148.png)
配置ThreadPoolExecutor
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173622760-391108682.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173623041-1613156015.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173623229-537309972.png)
![](https://images2015.cnblogs.com/blog/731047/201702/731047-20170209173623416-1630861528.png)