Java8的CompletionService使用与原理
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
https://www.cnblogs.com/shijiaqi1066/p/10454237.html
CompletionService是Java8的新增接口,JDK为其提供了一个实现类ExecutorCompletionService。这个类是为线程池中Task的执行结果服务的,即为Executor中Task返回Future而服务的。CompletionService的实现目标是任务先完成可优先获取到,即结果按照完成先后顺序排序。
CompletionService的使用非常简单。从源码查看ExecutorCompletionService类,该类只有三个成员变量:
public class ExecutorCompletionService<V> implements CompletionService<V> {
private final Executor executor;
private final AbstractExecutorService aes;
private final BlockingQueue<Future<V>> completionQueue;
...
}
可以看到ExecutorCompletionService主要是增强executor线程池的。Task包装后被塞入completionQueue,当Task结束,其Future就可以从completionQueue中获取到。
其基本原理可以参看下图:

CompletionService接口源码:
public interface CompletionService<V> {
// 提交
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;
}
例:向CompletionService中提交10个Task,当Task有任务返回则会优先从CompletionService内部的队列中获取到Task的Future。
package test;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestCompletionService {
public static void main(String[] args) {
Long start = System.currentTimeMillis();
//开启3个线程
ExecutorService exs = Executors.newFixedThreadPool(5);
try {
int taskCount = 10;
// 结果集
List<Integer> list = new ArrayList<Integer>();
List<Future<Integer>> futureList = new ArrayList<Future<Integer>>();
// 1.定义CompletionService
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(exs);
// 2.添加任务
for(int i=0;i<taskCount;i++){
Future<Integer> future = completionService.submit(new Task(i+1));
futureList.add(future);
}
// 3.获取结果
for(int i=0;i<taskCount;i++){
Integer result = completionService.take().get();
System.out.println("任务i=="+result+"完成!"+new Date());
list.add(result);
}
System.out.println("list="+list);
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭线程池
exs.shutdown();
}
}
static class Task implements Callable<Integer>{
Integer i;
public Task(Integer i) {
super();
this.i=i;
}
@Override
public Integer call() throws Exception {
if(i==5) {
Thread.sleep(5000);
}else{
Thread.sleep(1000);
}
System.out.println("线程:"+Thread.currentThread().getName()+"任务i="+i+",执行完成!");
return i;
}
}
}
Java8的CompletionService使用与原理的更多相关文章
- 迄今为止最硬核的「Java8时间系统」设计原理与使用方法
为了使本篇文章更容易让读者读懂,我特意写了上一篇<任何人都需要知道的「世界时间系统」构成原理,尤其开发人员>的科普文章.本文才是重点,绝对要读,走起! Java平台时间系统的设计方案 几乎 ...
- Java8线程池ThreadPoolExecutor底层原理及其源码解析
小侃一下 日常开发中, 或许不会直接new线程或线程池, 但这些线程相关的基础或思想是非常重要的, 参考林迪效应; 就算没有直接用到, 可能间接也用到了类似的思想或原理, 例如tomcat, jett ...
- CompletionService简介、原理以及小案例
博客1:http://www.oschina.net/question/12_11255 博客2: CompletionService简介 CompletionService与ExecutorServ ...
- 深入理解Java8中Stream的实现原理
Stream Pipelines 前面我们已经学会如何使用Stream API,用起来真的很爽,但简洁的方法下面似乎隐藏着无尽的秘密,如此强大的API是如何实现的呢?比如Pipeline是怎么执行的, ...
- ☕【Java技术指南】「并发编程专题」CompletionService框架基本使用和原理探究(基础篇)
前提概要 在开发过程中在使用多线程进行并行处理一些事情的时候,大部分场景在处理多线程并行执行任务的时候,可以通过List添加Future来获取执行结果,有时候我们是不需要获取任务的执行结果的,方便后面 ...
- 还在使用Future轮询获取结果吗?CompletionService快来了解下吧。
背景 二胖上次写完参数校验(<二胖写参数校验的坎坷之路>)之后,领导一直不给他安排其他开发任务,就一直让他看看代码熟悉业务.二胖每天上班除了偶尔跟坐在隔壁的前端小姐姐聊聊天,就是看看这些 ...
- SpringBoot 2.x (7):拦截器
类似以前SpringMVC的拦截器,但也有一些区别 SpringBoot的拦截器有两种方式: 第一种方式:过时的方式,适用于SpringBoot1.x的方式 package org.dreamtech ...
- [源码解析] 当 Java Stream 遇见 Flink
[源码解析] 当 Java Stream 遇见 Flink 目录 [源码解析] 当 Java Stream 遇见 Flink 0x00 摘要 0x01 领域 1.1 Flink 1.2 Java St ...
- Java8 中 ConcurrentHashMap工作原理的要点分析
简介: 本文主要介绍Java8中的并发容器ConcurrentHashMap的工作原理,和其它文章不同的是,本文重点分析了不同线程的各类并发操作如get,put,remove之间是如何同步的,以及这些 ...
随机推荐
- 异步fifo的Verilog实现
一.分析 由于是异步FIFO的设计,读写时钟不一样,在产生读空信号和写满信号时,会涉及到跨时钟域的问题,如何解决? 跨时钟域的问题:由于读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO ...
- 主成分分析(PCA)原理详解
一.PCA简介 1. 相关背景 在许多领域的研究与应用中,往往需要对反映事物的多个变量进行大量的观测,收集大量数据以便进行分析寻找规律.多变量大样本无疑会为研究和应用提供了丰富的信息,但也在一定程度上 ...
- 对Python源码加密及反编译前后对比
关于python的加密 目前软件开发商对 Python 加密时可能会有两种形式,一种是对python转成的exe进行 保护,另一种是直接对.py或者.pyc文件进行保护,下面将列举两种形式的保护流程. ...
- Python开发【项目】:选课系统-改良版
程序名称: 选课系统 角色:学校.学员.课程.讲师要求:1. 创建北京.上海 2 所学校2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开3. ...
- Windows下解压分卷压缩方法
各种压缩分卷格式 rar分卷格式是*.part1.rar,*.part2.rar 等等. 360分卷压缩出来的文件的名字是*.zip.001.*.zip002 等等. WinZip分卷压缩出来的文件名 ...
- 对 data属性的使用之一
- selenium python3
安装pip3 install selenium 查看版本pip3 show selenium 安装后还是提示找不到相应的模块 Mac安装PyCharm后,将已有工程导入,之前使用Mac终端执行脚本时正 ...
- 遇到问题---hosts不起作用问题的解决方法
c:\WINDOWS\system32\drivers\etc\hosts 文件的作用是添加 域名解析 定向 比如添加 127.0.0.1 www.baidu.com 那我们访问www.baidu. ...
- express-generator 自动生成服务器基本文件
(1) 安装 express-generator 构建工具 npm install -g express-generator 在命令行中用 npm 在全局安装 express-generator 脚手 ...
- iOS 设计模式-Block实现代理的逻辑
在A页面,点击跳转到B页面,B页面操作完,回到A页面,并刷新A页面的内容.典型的例子,就是在一个列表里,点击新增,跳到新增页面,新增完,把数据传回给列表页,并刷新列表页里的内容. 这个,我平时一般是通 ...