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第 ...
随机推荐
- [极客大挑战 2019]Http
0x00知识点 了解HTTP协议,使用bp伪造. 0x01 解题 首先查看源代码,找到Secret.php 访问 使用bp查看 提示我们需要来自该网址,直接改header头信息即可,我们可以通过使用r ...
- Linux(CENTOS7) Tomcat服务成功发布但局域网浏览器无法访问
问题 : 我在linux搭建了一个tomcat服务器,tomcat开启后,发现在局域网浏览器上无法访问该tomcat,浏览器报无法访问服务器错误,我查看了tomcat的日志,路径..../tomcat ...
- 1. react 基础 简介 及 环境搭建
一.简介 由 Facebook 推出 2013 年 开源 的 函数式编程的 使用人数最多的 前端框架 拥有健全的文档与完善的社区 ( 官网 ) react 16 称为 React Fiber ( 底层 ...
- JQuery 点击子控件事件,不会触发父控件的事件
$('.order-delete').on('tap', function (e) { console.log('删除1'); c ...
- StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
当时VS CODE内嵌的jupyter 交互界面的时候,出现了这个错误 原因是,这样的界面不支持行输入.可以使用cmd终端或其他方式运行该文件进行交互输入
- Maven依赖三板大斧
一:问题出现场景 记得有一次,面试时候面试官问了个问题,来哥们,“你们项目是maven搭建哈,你的项目里如果出现架包冲突了,你们怎么解决的?”. 我:......,装作很淡定,我们是通过报错,定位哪个 ...
- drf中的jwt使用与手动签发token、校验用户
jwt认证 1)session存储token,需要数据库参与,耗服务器资源.低效2)缓存存token,需要缓存参与,高效,不易集群3)客户端存token,服务器存签发与交易token的算法,高效,易集 ...
- C# 创建、部署和调用WebService的简单示例 (转)
C# 创建.部署和调用WebService的简单示例(转) 转自 https://www.cnblogs.com/Brambling/p/7266482.html webservice 可以用于分 ...
- UML- 其他需求制品有哪些?
1.其他需求 补充性规格说明(非功能性需求):性能/稳定性.文档.报表.许可授权等. 词汇表 设想:执行摘要. 业务规则(领域规则):如税法 2.准则 初始阶段无需对其他需求彻底分析.但花费一定时间 ...
- [原]how to view custom provider's events(collected without provider registered) by wpa
最近想使用etw作为高效的日志机制,也不想暴露机密信息(关键信息在msnifest文件中).也就是不能在客户机器上注册自己的provider,那需要manifest文件.这样采集回来的.etl文件如果 ...