java8异步_Java8新特性之:CompletableFuture
一. CompletableFuture
1.Future接口
Future设计的初衷:对将来某个时刻会发生的结果进行建模。
它建模了一种异步计算,返回一个执行运算结果的引用,当运算结束后,这个引用被返回给调用方。在Future中出发那些潜在耗时的操作把调用线程解放出来,让它能继续执行其他有价值的工作,不再需要等待耗时的操作完成。
Future的优点:比更底层的Thread更易用。
要使用Future,通常只需要将耗时的操作封装在一个Callable对象中,再将它提交给ExecutorService。ExecutorService executor = Executors.newCachedThreadPool();
Future future = executor.submit(new Callable() { //向ExecutorService提交一个Callable对象
@Override
public Double call() throws Exception {
return doSomeLongComputation(); //以异步方式在新的线程中执行耗时的操作
}
});
doSomethingElse(); //异步操作进行的同时,你可以做其他的事情
try {
//获取异步操作的结果,如果最终被阻塞,无法得到结果,那么在最多等待1秒钟之后退出
Double result = future.get(1, TimeUnit.SECONDS);
} catch (ExecutionException ee) {
//加上抛出一个异常
} catch (InterruptedException ie) {
//当前线程在等待过程中被中断
} catch (TimeoutException te) {
//在Future对象完成之前超过已过期
}
2. 实现异步API、代码避免阻塞
使用工厂方法supplyAsync创建CompletableFuturepublic Future getPriceAsync2(String product) {
return CompletableFuture.supplyAsync(() -> calculatePrice(product));
}
supplyAsync方法接受一个生产者(Supplier)作为参数,返回一个CompletableFuture对象,该对象完成异步执行后会读取调用生产者方法的返回值。
生产者方法会交由ForkJoinPool池中的某个执行线程(Executor)运行,但是你也可以使用supplyAsync方法的重载版本,传递第二个参数指定不同的执行线程执行生产者方法。
join方法等待异步操作结束
CompletableFuture类中的join方法和Future接口中的get有相同的含义,等待运行结束。并且也声明在Future接口中,唯一的不同是join方法不会抛出任何检测到的异常。因此使用它时不需要再使用try/catch语句块。public List findPrices(String product) {
//使用CompletableFuture以异步方式计算每种商品的价格
List> priceFutures = shops.stream()
.map(shop -> CompletableFuture.supplyAsync(() -> shop.getName() + " price is " + shop.getPriceAsync(product)))
.collect(Collectors.toList());
//等待所有异步操作结束
return priceFutures.stream().
map(CompletableFuture::join)
.collect(Collectors.toList());
}
使用定制执行器
创建一个配有线程池的执行器。
线程数的选择:N(threads) = N(CPU) * U(CPU) * (1 + W/C)
-- N(CPU):处理器的核的数目,可以通过Runtime.getRuntime().availableProcessors()得到;
-- U(CPU):期望的CPU利用率(该值应该介于0和1之间);
-- W/C:等待时间与计算时间的比率。//创建一个线程池,线程池中线程的数目为100和商店数目二者中较小的一个值(这里100为线程池的上限)
private final Executor executor = Executors.newFixedThreadPool(Math.min(shops.size(), 100), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true); //使用守护线程--这种方式不会阻止程序的关停
return t;
}
});
集合进行并行计算有两种方式:并行流和CompletableFutures。
-- 计算密集型操作,并且没有I/O,推荐使用Stream接口。因为实现简单,同时效率也可能是最高的(如果所有的线程都是计算密集型的,那就没有必要创建比处理器核数更多的线程);
-- 如果并行的工作单元还涉及等待I/O的操作(包括网络连接等待),那么使用CompletableFuture灵活性更好。这种情况下处理流的流水线中如果发生I/O等待,流的延迟特性会让我们很难判断到底什么时候触发了等待。
3. 对多个异步任务进行流水线操作
thenApply:将一个由字符串转换Quote的方法作为参数传递给他
thenCompose:该方法允许你对两个异步操作进行流水线,第一个操作完成时,将其结果作为参数传递给第二个操作。
对第一个CompletableFuture对象调用thenCompose,并向其传递一个函数。当第一个CompletableFuture执行完毕后,他的结果将作为该函数的参数,这个函数的返回值是以第一个CompletableFuture的返回做输入计算出的第二 个CompletableFuture对象。
使用thenCompose减少很多线程切换开销。
thenCombine:将两个CompletableFuture对象结果整合起来。该方法接收名为BiFunction的第二参数,这个参数定义了两个CompletableFuture对象完成计算后,如何合并。
thenAccept:方法接收CompletableFuture执行完毕后的返回值做参数。不必等待那些还未返回的结果。
java8异步_Java8新特性之:CompletableFuture相关推荐
- Java基础学习总结(33)——Java8 十大新特性详解
Java8 十大新特性详解 本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API ...
- java lambda表达式详解_java8新特性-Lambda表达式的详解(从0开始)
这几天复习了java8的一些新特性,作为一个从java5以来最具革命性的版本,一直没有来得及总结.本系列文章主要是从<java8实战>总结的.这是第一篇文章主要介绍java8的lambda ...
- Java基础笔记-Java8及其他新特性
第十六章 Java8及其他新特性 16.1 Java8新特性简介 16.2 lambda表达式和函数式接口 16.3 方法引用与构造器引用 16.4 StreamAPI的使用 16.5 Optiona ...
- JAVA8 十大新特性详解
JAVA8 十大新特性详解 http://www.jb51.net/article/48304.htm java7和java6比较有什么不同 转载于:https://www.cnblogs.com/y ...
- Java8的一些新特性
Java8的一些新特性 文章目录 Java8的一些新特性 1.函数式接口 2.Lambda表达式 2.1.介绍 2.2.案例 2.3.案例讲解 3.方法引用 3.1.介绍 3.2.案例 4.Strea ...
- java8新特性_Java8新特性之Date API|乐字节
大家好,我是乐字节的小乐,上篇文章讲述了<Java8新特性之Optional>,接下来,小乐将接着讲述Java8新特性之Date API 2019日历 Java8之Date API Jav ...
- java8 stream遍历_Java8新特性:Stream流详解
1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel agg ...
- java8 stream 做累加_Java8新特性之Stream(上)|乐字节
上次给大家介绍了Java8新特性之方法引用,大家可以点击回顾下.接下来小乐继续给大家带来Java8新特性之Stream ,流是Java8最重要的内容,小乐准备分上下两部分介绍,今天是上部. 5.1.什 ...
- java8 lambda map排序_Java8新特性第3章(Stream API)
转载请注明出处:https://zhuanlan.zhihu.com/p/20540202 Stream作为Java8的新特性之一,他与Java IO包中的InputStream和OutputStre ...
最新文章
- 西游记里河水让人怀孕的秘密:是寄生虫!我往河里放了寄生虫!
- LayoutInflater中调用系统服务
- python 正则re模块
- python数独游戏源代码100行_python实现自动解数独小程序
- hibernate+spring 注解 对事务的一些信息 (还没有整理)
- Python地理数据处理库GDAL调研记录
- win11如何加快搜索速度 Windows11更改文件索引加快搜索速度的设置方法
- java 占位符_Java重要知识点
- css3中的zoom属性以及jquery中css()方法操作元素的属性
- Serializer对象
- 小米手机MIUI安装Google服务框架和Google Play的教程
- 小白对于Linux的学习
- 终端图像处理实践:AR全景动态贴纸方案简介
- 基于海思AI芯片的智能视频分析边缘网关
- opencv3学习:reshape函数
- 中控门禁无法添加设备,提示表结构不存在或接收超时
- 功能点算法及在软件测试中的应用
- 大数据产品价值主张_十年之后
大数据的价值主张
- 山区地貌图 在某山区(平面区域(0,2800)´(0,2400)内,单位:米)测得一些地点的高程(单位:米)如表1,试作出该山区的地貌图.
- Linux入门(一)
热门文章
- 怎么打开外部文件_保存的DWG文件再次用CAD打开时提示文件损坏了怎么办?【AutoCAD教程】...
- word文档无法连接服务器,sql数据库无法连接服务器解决办法绝对有效
- 阿里开源台柱 Ant Design 源码仓库被删了...
- 赠书:全球首本VS Code中文书来了,高效编程秘诀全收录!
- 面试:说说你对“零拷贝”的理解?
- 它又来了!Fastjson 被发现其用于安全控制的开关autotype限制可被绕过...你方了没?...
- 面试官,别再问高并发了!
- IntelliJ IDEA 2019.3发布,饱受性能诟病的2019.2版本终于成为过去式
- java ajax jquery分页插件_分享精心挑选的12款优秀jQuery Ajax分页插件和教程
- 微信小程序wxparse内容页显示不出来不能正确解析html代码