我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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中怎么正确高效的使用并行流”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

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

JAVA8 Stream流中的reduce()方法怎么使用

这篇文章主要介绍“JAVA8 Stream流中的reduce()方法怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JAVA8 Stream流中的reduce()方法怎么使用”文章能帮助大家解
2023-07-05

Swift中的RegexBuilder怎么正确使用

本篇内容主要讲解“Swift中的RegexBuilder怎么正确使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Swift中的RegexBuilder怎么正确使用”吧!前言在我们日常的项目开发
2023-07-05

springboot中的redis怎么正确使用

这篇“springboot中的redis怎么正确使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springboot中的r
2023-06-30

MySQL事务在Python中如何正确地进行管理和提交?(使用Python如何有效地管理并提交MySQL事务?)

MySQL事务在Python中至关重要,它确保数据库操作的原子性和一致性。通过start_transaction开始一个事务,随后执行一系列插入、更新或删除操作。当完成所有操作后,通过commit提交事务,将这些操作永久生效。若出现错误,可通过rollback回滚事务,撤销所有已执行的操作。最佳实践包括使用with语句管理事务、设置适当的隔离级别、处理异常和保持事务简短。通过正确管理和提交事务,可以保证数据的完整性和一致性,有效利用数据库资源。
MySQL事务在Python中如何正确地进行管理和提交?(使用Python如何有效地管理并提交MySQL事务?)
2024-04-02

怎么使用正则表达式替换JavaScript文本中的换行符

这篇文章主要介绍“怎么使用正则表达式替换JavaScript文本中的换行符”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用正则表达式替换JavaScript文本中的换行符”文章能帮助大家解决问
2023-07-06

怎么使用Golang中的正则表达式库来进行字符串替换

本篇内容主要讲解“怎么使用Golang中的正则表达式库来进行字符串替换”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Golang中的正则表达式库来进行字符串替换”吧!一、正则表达式基础在
2023-07-05

Java项目中的HTML标签怎么使用正则表达式进行删除

这篇文章给大家介绍Java项目中的HTML标签怎么使用正则表达式进行删除,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。具体如下:package com.xz.cxzy.utils;import java.util.re
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录