前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用并行流还是CompletableFuture(四)

使用并行流还是CompletableFuture(四)

作者头像
栋先生
发布于 2018-09-29 09:01:57
发布于 2018-09-29 09:01:57
1.3K00
代码可运行
举报
文章被收录于专栏:Java成长之路Java成长之路
运行总次数:0
代码可运行

我们知道,对集合进行计算,可以使用并行和异步的CompletableFuture操作,都可以加快其处理,那么到底该使用并行还是异步呢?

并行流和CompletableFuture

如上篇博客中所讲到的getPrice()方法,使用并行方式处理,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public List<String> findPricesParallel(String product) {
        return shops.parallelStream()
                .map(shop -> shop.getName() + " price is " + shop.getPrice(product))
                .collect(Collectors.toList());
    }

使用CompletableFuture操作处理,代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public List<String> findPricesFuture(String product) {
        List<CompletableFuture<String>> priceFutures =
                shops.stream()
                        .map(shop -> CompletableFuture.supplyAsync(() -> shop.getName() + " price is "
                                + shop.getPrice(product)))
                        .collect(Collectors.toList());

        List<String> prices = priceFutures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
        return prices;
    }

以下两种写法的区别是什么呢?它们内部采用的是同样的通用线程池,默认都使用固定数目的线程,具体线程数取决于Runtime.getRuntime().availableProcessors()的返回值。然而,CompletableFuture具有一定的优势,因为它允许你对执行器(Executor)进行配置,尤其是线程池的大小,让它以更适合应用需求的方式进行配置,满足程序的要求,而这是并行流API无法提供的。让我们看看你怎样利用这种配置上的灵活性带来实际应用程序性能上的提升。

使用定制的执行器

就这个主题而言,明智的选择似乎是创建一个配有线程池的执行器,线程池中线程的数目取决于你预计你的应用需要处理的负荷,但是你该如何选择合适的线程数目呢? 你的应用99%的时间都在等待商店的响应,所以估算出的W/C比率为100。这意味着如果你 期望的CPU利用率是100%,你需要创建一个拥有400个线程的线程池。实际操作中,如果你创建 的线程数比商店的数目更多,反而是一种浪费,因为这样做之后,你线程池中的有些线程根本没 有机会被使用。出于这种考虑,我们建议你将执行器使用的线程数,与你需要查询的商店数目设 定为同一个值,这样每个商店都应该对应一个服务线程。不过,为了避免发生由于商店的数目过 多导致服务器超负荷而崩溃,你还是需要设置一个上限,比如100个线程。代码清单如下所示。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //创建一个线程池,线程池中线程的数目为100 和商店数目 二者中较小 的一个值
    private final Executor executor = Executors.newFixedThreadPool(shops.size(), new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            //使用守护线程——这种方式不会阻止程序的关停
            t.setDaemon(true);
            return t;
        }
    });

注意:你现在正创建的是一个由守护线程构成的线程池。Java程序无法终止或者退出一个正 在运行中的线程,所以最后剩下的那个线程会由于一直等待无法发生的事件而引发问题。与此相 反,如果将线程标记为守护进程,意味着程序退出时它也会被回收。这二者之间没有性能上的差 异。

现在,你可以将执行器作为第二个参数传递给supplyAsync工厂方法了。比如,你现在可 以按照下面的方式创建一个可查询指定商品价格的CompletableFuture对象:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 CompletableFuture.supplyAsync(() -> shop.getName() + " price is " +
                                        shop.getPrice(product), executor);

结论

目前为止,你已经知道对集合进行并行计算有两种方式:要么将其转化为并行流,利用map这样的操作开展工作,要么枚举出集合中的每一个元素,创建新的线程,在Completable- Future内对其进行操作。后者提供了更多的灵活性,你可以调整线程池的大小,而这能帮助你确保整体的计算不会因为线程都在等待I/O而发生阻塞。 我们对使用这些API的建议如下。

  • 如果你进行的是计算密集型的操作,并且没有I/O,那么推荐使用Stream接口,因为实现简单,同时效率也可能是最高的(如果所有的线程都是计算密集型的,那就没有必要创建比处理器核数更多的线程)。
  • 反之,如果你并行的工作单元还涉及等待I/O的操作(包括网络连接等待),那么使用CompletableFuture灵活性更好,你可以像前文讨论的那样,依据等待/计算,或者 W/C的比率设定需要使用的线程数。这种情况不使用并行流的另一个原因是,处理流的 流水线中如果发生I/O等待,流的延迟特性会让我们很难判断到底什么时候触发了等待。

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2nvbeahjzomcw

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年08月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C/C++生态工具链——编译构建工具CMake/CMakeList初探
CMake的全称是Cross-platform Make。我第一次参与Linux C++开发时使用的工具是Make,而后开始切换到CMake,一开始以为CMake是和C语言有关,原来开头的C表示它可以跨平台。
Coder-ZZ
2023/02/23
3.1K0
C/C++生态工具链——编译构建工具CMake/CMakeList初探
CMake学习笔记(一)——CMake官网教程
剑影啸清寒
2018/01/02
4.5K0
【CMake教程】(五)CMake 配置install打包
我们编译生成的可执行文件一般,会生成在当前的编译路径下,也就是build或者release路径下。那么如何将编译生成的可执行文件和库文件打包到一起进行发布那?本片教程我们将讲述如何在cmake中配置install的打包路径。下面我们将以mathlib库和头文件为例子进行配置。
CNNer
2020/07/21
9.4K0
【CMake教程】(三)CMake 配置指定C++11编译的标准
  本文主要讲述如何使用CMakeLists.txt,指定当前程序的C++编译标准。
CNNer
2020/11/04
34.8K0
【CMake教程】(三)CMake 配置指定C++11编译的标准
CMAKE使用手记
首先感谢那位叫“任麒麟”的网友整理的PDF,有心了。 我也忘了哪里下载的,不过确实挺全的。
看、未来
2021/10/09
5820
CMake学习笔记(二)——CMake语法
剑影啸清寒
2018/01/02
6K0
深入浅出CMake(一):基础篇
CMake 是一个跨平台的编译构建工具,用来自动化生成 Makefile 之类的构建文件的。
Frank909
2019/03/15
1.4K0
CMake 入门教程:从零开始构建 C-C++ 项目
首先,需要下载并安装CMake。可以从CMake官网下载。如果404 Not Found,可以试一下这个国内镜像网址下载地址。
小万哥
2023/05/24
1.5K0
CMake 入门教程:从零开始构建 C-C++ 项目
CMake简介及使用实例
CMake是一个跨平台的建构系统的工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的构建文档makefile或者project文件,描述系统建构的过程。还能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CmakeLists.txt。CMake并不直接建构出最终的软件,而是产生标准的建构档(如 Unix的 Makefile或 Windows Visual C++的 projects/workspaces),然后再依一般的构建方式使用。
恋喵大鲤鱼
2018/08/03
2.7K0
CMake用法,这篇文章讲全了
CMake是一个开源的、跨平台的自动化构建系统,用于管理软件构建过程。它通过编写配置文件(CMakeLists.txt),自动生成适合不同编译器和操作系统的构建脚本或项目文件。CMake以其强大的跨平台能力成为众多开发者构建项目的首选工具。无论是简单的单文件项目,还是复杂的多文件、多文件夹乃至集成第三方库的大型工程,CMake都能游刃有余。本文将结合实例详细介绍cmake的常见用法,包括单文件、多文件、多文件夹以及引用第三方库等。
程序员的园
2024/07/18
4290
CMake用法,这篇文章讲全了
烛照:使用CMake管理机器视觉后端算法库
大家好我是周旋,欢迎学习【烛照:QT机器视觉软件开发】项目。手把手视频教程已经在网站开始更新:
周旋
2024/05/03
2470
烛照:使用CMake管理机器视觉后端算法库
初识CMake
CMake 是一个 跨平台的 项目构建工具,CMake不过就是比makefile更高级一些,makefile不仅写起来繁琐,并且不同平台有所差异。
用户11029129
2025/04/14
1730
初识CMake
Linux CMake 快速使用(二)——动态库创建与链接
moreFile文件夹下分别是build、src文件夹以及主CMakeLists.txt文件
用户5908113
2020/05/07
2.8K0
Cmake的使用
有了Cmake以后,只需要编写一个CmakeLists文件就可以对应将一个C++工程不通操作系统
全栈程序员站长
2022/09/22
1.6K0
Cmake的使用
cmake用法
示例源码 在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:
用户2929716
2018/08/23
1.3K0
cmake用法
CMake编写总结
make和CMake之间的关系是CMake 通过命令可以生成make执行的Makefile文件,所以说CMake 是make 的升级版的生成工具
impressionyang
2020/08/27
1.1K0
cmake快速入门「建议收藏」
cmake是kitware公司以及一些开源开发者在开发几个工具套件(VTK)的过程中所产生的衍生品。后来经过发展,最终形成体系,在2001年成为一个独立的开放源代码项目。其官方网站是www.cmake.org,可以通过访问官方网站来获得更多关于cmake的信息,而且目前官方的英文文档比以前有了很大的改进,可以作为实践中的参考手册。
全栈程序员站长
2022/09/13
1.3K0
cmake快速入门「建议收藏」
Linux下CMake简明教程
CMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置文件去生成本地的Makefile,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接拿到其它平台上使用,无需修改,非常方便。
全栈程序员站长
2022/09/01
2.2K0
CMake使用总结
CMake意为cross-platform make,可用于管理c/c++工程。CMake解析配置文件CMakeLists.txt生成Makefile,相比直接用Makefile管理工程,CMake更灵活和简单。
bear_fish
2018/09/19
1.9K0
【AI白身境】只会用Python?g++,CMake和Makefile了解一下
在学习CMake和和Makefile之前我们先学下g++这个工具,大家或许会问为什么要学g++,不应该直接学CMake和Makefile吗。实际上如果你不掌握g++根本就不会写Makefile,因为它实际上就是对g++代码的整理,有了Makefile,执行程序会更加快速方便。另外CMake就是为了简化Makefile的编写,它可以自动生成Makefile。
用户1508658
2019/07/26
1.8K0
【AI白身境】只会用Python?g++,CMake和Makefile了解一下
相关推荐
C/C++生态工具链——编译构建工具CMake/CMakeList初探
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验