返回顶部
首页 > 资讯 > 精选 >Java8中怎么正确高效的使用并行流
  • 643
分享到

Java8中怎么正确高效的使用并行流

2023-06-25 13:06:48 643人浏览 安东尼
摘要

这篇文章主要为大家展示了“Java8中怎么正确高效的使用并行流”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java8中怎么正确高效的使用并行流”这篇文章吧。正确使用并行流,避免共享可变状态错用

这篇文章主要为大家展示了“Java8中怎么正确高效的使用并行流”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java8中怎么正确高效的使用并行流”这篇文章吧。

正确使用并行流,避免共享可变状态

错用并行流而产生错误的首要原因,就是使用的算法改变了某些共享状态。下面是另一种实现对前n个自然数求和的方法,但这会改变一个共享累加器:

public static long sideEffectSum(long n) {Accumulator accumulator = new Accumulator();LongStream.rangeClosed(1, n).forEach(accumulator::add);return accumulator.total;}public class Accumulator {public long total = 0;public void add(long value) { total += value; }}

有什么问题呢?

它在本质上就是顺序的。每次访问 total 都会出现数据竞争。如果用同步来修复,那就完全失去并行的意义了。

为了说明这一点,让我们试着把 Stream 变成并行的:

public static long sideEffectParallelSum(long n) {Accumulator accumulator = new Accumulator();LongStream.rangeClosed(1, n).parallel().forEach(accumulator::add);return accumulator.total;}

测试下,输出

Java8中怎么正确高效的使用并行流

Java8中怎么正确高效的使用并行流

性能无关紧要了,唯一要紧的是每次执行都会返回不同的结果,都离正确值差很远。这是由于多个线程在同时访问累加器,执行 total += value ,而这却不是一个原子操作。问题的根源在于, forEach 中调用的方法有副作用它会改变多个线程共享的对象的可变状态。

要是你想用并行 Stream 又不想引发类似的意外,就必须避免这种情况。

所以共享可变状态会影响并行流以及并行计算,要避免共享可变状态,确保并行 Stream 得到正确的结果。

高效使用并行流

是否有必要使用并行流?

  • 如果有疑问,多次测试结果。把顺序流转成并行流轻而易举,但却不一定是好事

  • 留意装箱。自动装箱和拆箱操作会大大降低性能

Java 8中有原始类型流( IntStream 、LongStream 、 DoubleStream )来避免这种操作,但?有可能都应该用这些流。

  • 有些操作本身在并行流上的性能就比顺序流差。特别是 limit 和 findFirst 等依赖于元素顺序的操作,它们在并行流上执行的代价非常大。

例如, findAny 会比 findFirst 性能好,因为它不一定要按顺序来执行。可以调用 unordered 方法来把有序流变成无序流。那么,如果你需要流中的n个元素而不是专门要前n个的话,对无序并行流调用limit 可能会比单个有序流(比如数据源是一个 List )更高效。

  • 还要考虑流的操作流水线的总计算成本。

设N是要处理的元素的总数,Q是一个元素通过流水线的大致处理成本,则N*Q就是这个对成本的一个粗略的定性估计。Q值较高就意味着使用并行流时性能好的可能性比较大。

  • 对于较小的数据量,选择并行流几乎从来都不是一个好的决定。并行处理少数几个元素的好处还?不上并行化造成的额外开销

  • 要考虑流背后的数据结构是否易于分解。

例如, ArrayList 的拆分效率比 LinkedList高得多,因为前者用不着遍历就可以平均拆分,而后者则必须遍历。另外,用 range 工厂方法创建的原始类型流也可以快速分解。

  • 流自身的特点,以及流水线中的中间操作修改流的方式,都可能会改变分解过程的性能。

例如,一个 SIZED 流可以分成大小相等的两部分,这样每个部分都可以比较高效地并行处理,但筛选操作可能丢弃的元素个数却无法预测,导致流本身的大小未知。

  • 还要考虑终端操作中合并步骤的代价是大是小(例如 Collector 中的 combiner 方法)

如果这一步代价很大,那么组合每个子流产生的部分结果所付出的代价就可能会超出通过并行流得到的性能提升。

流的数据源和可分解性

Java8中怎么正确高效的使用并行流

最后, 并行流背后使用的基础架构是Java 7中引入的分支/合并框架了解它的内部原理至关重要。

以上是“Java8中怎么正确高效的使用并行流”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: Java8中怎么正确高效的使用并行流

本文链接: https://lsjlt.com/news/304862.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java8中怎么正确高效的使用并行流
    这篇文章主要为大家展示了“Java8中怎么正确高效的使用并行流”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java8中怎么正确高效的使用并行流”这篇文章吧。正确使用并行流,避免共享可变状态错用...
    99+
    2023-06-25
  • Java8 如何正确高效的使用并行流
    目录正确使用并行流,避免共享可变状态高效使用并行流流的数据源和可分解性java 并行计算的几点实践总结正确使用并行流,避免共享可变状态 错用并行流而产生错误的首要原因,就是使用的算法...
    99+
    2024-04-02
  • 怎么让python程序正确高效地并发
    这篇文章主要介绍“怎么让python程序正确高效地并发”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么让python程序正确高效地并发”文章能帮助大家解决问题。python线程何时需要拥有GIL?...
    99+
    2023-07-02
  • 使用Java8中Optional机制的正确姿势
    前言Java8带来的函数式编程特性对于习惯命令式编程的程序员来说还是有一定的障碍的,我们只有深入了解这些机制的方方面面才能运用自如。Null的处理在JAVA编程中是出了try catch之外的另一个头疼的问题,需要大量的非空判断模板代码,程...
    99+
    2023-05-30
    java8 optional 使用
  • 如何正确的在Java8中使用lambda表达式
    如何正确的在Java8中使用lambda表达式?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.基本介绍lambda表达式,即带有参数的表达式,为了更清晰地理解lambda...
    99+
    2023-05-31
    java8 lambda ava
  • lambda表达式如何正确的在Java8项目中使用
    这篇文章给大家介绍lambda表达式如何正确的在Java8项目中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在Java8 里面Lambda是最火的主题,不仅仅是因为语法的改变,更重要的是带来了函数式编程的思想,我...
    99+
    2023-05-31
    java8 lambda ava
  • JAVA8 Stream流中的reduce()方法怎么使用
    这篇文章主要介绍“JAVA8 Stream流中的reduce()方法怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JAVA8 Stream流中的reduce()方法怎么使...
    99+
    2023-07-05
  • 怎么正确使用PostgreSQL中的OR
    本篇内容介绍了“怎么正确使用PostgreSQL中的OR”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在S...
    99+
    2024-04-02
  • springboot中的redis怎么正确使用
    这篇“springboot中的redis怎么正确使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springboot中的r...
    99+
    2023-06-30
  • Swift中的RegexBuilder怎么正确使用
    本篇内容主要讲解“Swift中的RegexBuilder怎么正确使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Swift中的RegexBuilder怎么正确使用”吧!前言在我们日常的项目开发...
    99+
    2023-07-05
  • java实用型-高并发下RestTemplate的正确使用说明
    目录前言一、RestTemplate是什么?二、如何使用1.创建一个bean2.使用步骤三、高并发下的RestTemplate使用1.设置预热功能2.合理设置maxtotal数量总结...
    99+
    2024-04-02
  • asp中response.flush怎么正确使用
    在ASP中,Response.Flush方法用于将所有尚未发送到客户端的输出发送到客户端。这可以用于实时地将输出发送到客户端,而不是...
    99+
    2023-08-19
    asp
  • stream中怎么正确使用peek
    这篇文章主要讲解了“stream中怎么正确使用peek”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“stream中怎么正确使用peek”吧!简介自从JDK中引入了stream之后,仿佛一切都...
    99+
    2023-07-05
  • C++中怎么正确使用hashmap
    这篇“C++中怎么正确使用hashmap”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++中怎么正确使用hashmap”文...
    99+
    2023-07-05
  • java中println怎么正确使用
    在Java中,`println`是一个用于输出的方法,用于在控制台中打印一行文本。它的正确使用方式如下: 打印字符串: Syst...
    99+
    2023-10-28
    java
  • sql中comment怎么正确使用
    在SQL中,可以使用注释来为代码提供说明或者备注。注释可以简短描述SQL查询的目的、功能或者其他相关信息,让其他开发人员能够更容易地...
    99+
    2024-04-09
    sql
  • 如何在Go语言中使用正确的数据类型实现高效的并发和存储?
    Go语言是一种强大的编程语言,旨在为现代计算机体系结构提供高效的编程体验。在Go语言中,正确的数据类型选择可以实现高效的并发和存储操作。本文将介绍如何在Go语言中使用正确的数据类型实现高效的并发和存储。 一、并发 Go语言的并发模型是基于g...
    99+
    2023-08-20
    并发 存储 数据类型
  • MySQL性能优化之如何高效正确的使用索引
    实践是检验真理的唯一途径,本篇只是站在索引使用的全局来定位的,你只需要通读全篇并结合具体的例子,或回忆以往使用过的地方,对整体有个全面认识,并理解索引是如何工作的,就可以了。在后续使用索引,或者优化索引时,可以从这些...
    99+
    2022-05-14
    MySQL 索引 MySQL 优化索引 MySQL 高效使用索引
  • 怎么正确使用香港高防网站空间
    正确使用香港高防网站空间的方法:1、定期扫描香港高防网站空间的程序以及文件,排查服务器潜在安全隐患;2、使用充足的机器承受攻击,从而消耗攻击资源、减少网络攻击带来的影响;3、香港高防网站空间可以对访问者的来源进行检查,从而将虚假IP进行过滤...
    99+
    2024-04-02
  • Go中怎么正确使用对枚举
    本篇内容主要讲解“Go中怎么正确使用对枚举”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Go中怎么正确使用对枚举”吧!枚举是强类型编程语言中的一种类型,由一组名称和值组成。通常用来在编程语言中充...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作