Java 线程总结(十四)
1、在异步任务进程中,一种常见的场景是,主线程提交多个异步任务,然后希望有任务完成就处理结果,并且按任务完成顺序逐个处理,对于这种场景,Java 并发包提供了一个方便的方法,使用 CompletionService,这是一个接口,它的实现类是 ExecutorCompletionService。
2、与 ExecutorService 一样,CompletionService 也可以提交异步任务,它的不同是,它可以按任务完成顺序获取结果,其具体定义为:
1
2
3
4
5
6
7
public interface <> {
Future<V> submit(Callable<V> task);
Future<V> submit(Runnable task, V result);
Future<V> take() throws InterruptedException;
Future<V> poll();
Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;
}
submit 方法与 ExecutorService 是一样的,多了 take 和 poll 方法,它们都是获取下一个完成任务的结果,take() 会阻塞等待,poll() 会立即返回,如果没有已完成的任务,返回 null,带时间参数的 poll 方法会最多等待限定的时间。
2、CompletionService 的主要实现类是 ExecutorCompletionService,它依赖于一个 Executor 完成实际的任务提交,而自己主要负责结果的排队和处理。它的构造方法有两个:
1
2
public ExecutorCompletionService(Executor executor)
public ExecutorCompletionService(Executor executor, BlockingQueue<Future<V>> completionQueue)
至少需要一个 Executor 参数,可以提供一个 BlockingQueue 参数,用作完成任务的队列,没有提供的话,ExecutorCompletionService 内部会创建一个 LinkedBlockingQueue。
3、ExecutorCompletionService 是怎么让结果有序处理的呢?
因为它有一个额外的队列,每个任务完成之后,都会将代表结果的 Future 入队。在 FutureTask 中,任务完成后,不管是正常完成、异常结束、还是被取消,都会调用 finishCompletion 方法,而该方法会调用一个 done 方法 protected void done() { } 该方法的实现为空,但它是一个 protected 方法,子类可以重写该方法。ExecutorCompletionService 的内部类 QueueingFuture 中重写了该方法。
在 ExecutorCompletionService 中,提交的任务类型不是一般的 FutureTask,而是一个子类 QueueingFuture
大专栏 Java 线程总结(十四)>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture(f));
return f;
}
----------------------------
private final BlockingQueue<Future<V>> completionQueue;
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}
---------------------------
而 ExecutorCompletionService 的 take/poll 方法就是从该队列获取结果:
1
2
3
public Future<V> take() throws InterruptedException {
return completionQueue.take();
}
4、AbstractExecutorService 的 invokeAny 的实现,就利用了 ExecutorCompletionService,它的基本思路是,提交任务后,通过 take 方法获取结果,获取到第一个有效结果后,取消所有其他任务。
5、CompletionService 它通过一个额外的结果队列,方便了对于多个异步任务结果的处理。
参考博客
Java编程的逻辑 - 方便的 CompletionService
Java 线程总结(十四)的更多相关文章
- “全栈2019”Java多线程第十四章:线程与堆栈详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第二十四章:等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java进阶(三十四)Integer与int的种种比较你知道多少?
Java进阶(三十四)Integer与int的种种比较你知道多少? 前言 如果面试官问Integer与int的区别:估计大多数人只会说到两点:Ingeter是int的包装类,注意是一个类:int的初值 ...
- 《Java程序设计》十四次作业
<Java程序设计>十四次作业实验总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 3. 代码量统计 周次 总代码量 新增代码量 总文件数 新增 ...
- “全栈2019”Java异常第十四章:将异常输出到文本文件中
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...
- “全栈2019”Java第八十四章:接口中嵌套接口详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第七十四章:内部类与静态内部类相互嵌套
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第六十四章:接口与静态方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第五十四章:多态详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
随机推荐
- postman问题
问题1:postman请求出现 'SSL certificate verification' ,实际为https的问题 解决: 1)关闭fiddler 2)或在File > Settings & ...
- protobuf 的enum与string转换
c/c++ enum 介绍 说起c/c++ 的enum,比起python 真的是方便简洁 enum type{ type1 = 0, type2 } enum的元素对应的int 默认从0 开始依次增加 ...
- 2020 年最流行的 Java 开发技术
不知不觉间,2020 年即将于十几天之后到来,作为技术圈中你,准备好迎接最新的变化了吗?在本文中,我们将以编程界最常用的编程语言 Java 为例,分享最为主流的技术与工具. 作者 | divyesh. ...
- 函数的配置对象Configuration Objects
配置对象通常用在API库的实现中,当程序中需要编写要多次的模块,也可以采用这种模式.这种模式的好处是接口明确,扩展方便.比如,一个 addPerson在设计的最初需要两个参数作为初始化时人的姓名: f ...
- Aras Innovator时间验证
//方法名:bcs_Nexteer_CheckTime //功能描述:开始和结束日期对比 //原作者:joe //创建时间:20141226 //版权所有(C)JOE.FAN //debugger; ...
- JQuery select,checkbox用法 文本框只能输入数字
记录一下,方便查找 a.文本框只能输入数字 onkeyup='this.value=this.value.replace(/\D/gi,"")' eg: <input typ ...
- 【MySQL参数】-innodb_additional_mem_pool_size
原博客:https://yq.aliyun.com/articles/32384
- MyBatis从入门到精通(第9章):Spring集成MyBatis(中)
MyBatis从入门到精通(第9章):Spring集成MyBatis(中) 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法.应该将应用自身的设计和具体 ...
- python编程:从入门到实践----第五章:if语句>练习
5-1 条件测试 :编写一系列条件测试:将每个测试以及你对其结果的预测和实际结果都打印出来. a. 详细研究实际结果,直到你明白了它为何为True 或False b. 创建至少2个测试,且其中结果分别 ...
- ubuntu下Django的搭建
工具:Window下的pycharm .VirtualBox下的Ubuntu系统.非必需的Xshell(远程连接工具) 现在针对各种包或python版本不能共存或包不能很好下载的问题,开始流行使用虚拟 ...