Java 8的新并行API - 魅力与炫目背后
这是一篇译文,原文链接见这里。
本文同时发表在ImportNew上,转载请注明出处。

我很擅长同时处理多项任务。就算是在写这篇博客的此刻,我仍然在为昨天在聚会上发表了一个让大家都感到诧异的评论而觉得尴尬。好吧,好消息是我并不孤单——Java 8在多任务处理方面同样很优秀。让我们来看看它是怎么做的。
在Java 8引入的新功能中,有很重要的一项是并行数组处理。这项新功能使得我们能够使用可以利用多核体系结构的Lambda表达式来对对数组的元素进行排序,过滤和分组。这里的重点是,Java程序员只需要非常少的工作就可以立刻使程序的性能获得提升。非常酷。
问题来了。这项新功能有多快?我应该什么时候使用它?好吧,答案有点让人沮丧——这依赖于具体的情况。要知道依赖什么情况吗?请继续阅读。
新的API
Java8的新并行操作API十分灵活。让我们一起看几个我们要用来做测试的例子。
1. 使用多核对数组进行排序:
Arrays.parallelSort(numbers);
2. 根据特定的条件(比如:素数和非素数)对数组进行分组:
Map<Boolean, List<Integer>> groupByPrimary = numbers
.parallelStream().collect(Collectors.groupingBy(s -> Utility.isPrime(s)));
3. 对数组进行过滤:
Integer[] prims = numbers.parallelStream().filter(s -> Utility.isPrime(s))
.toArray();
跟自己写多线程程序来实现相同的功能比较,生产力提高太多了!在这个新的体系中,我个人最喜欢的是一个叫Spliterator的新概念,将一个集合分成多个块,并行处理这多个块并将处理结果汇合到一起。就像它的哥哥iterator,它也被用来遍历一个集合的元素,只不过它更加灵活,允许你编写检查和分离集合的自定义行为,并在遍历时直接插入。
它的性能如何?
为了测试这些并行操作API的性能, 我在两种情况(低竞争和高竞争)下进行了实验。原因是单独运行一个多核算法,往往会有好的性能,但在真实的服务器环境中运行,情况就完全不同了。真实环境中往往有大量的线程在竞争宝贵的CPU时间片以处理消息或用户请求,由于竞争的存在,程序的性能就降低了。所以我进行了接下来的测试。我首先随机生成了长度为100K的整数数组,这些整数的取值在0到1百万之间。然后我分别使用传统的顺序方法和新的Java 8的并行API对这个数组进行了排序,分组和过滤。结果并不使人惊讶。
- 快速排序快了4.7倍
- 分组快了5倍
- 过滤快了5.5倍
这可以说明java 8的并行API具有非常好的性能吗?很不幸,不能。

*测试结果与运行了100次的附加测试结果一致。
*测试机器为MBP,i7四核。
在有负载的情况下会发生什么呢?
目前为止新API的性能表现非常出色,原因是线程之间对CPU的时间片的竞争非常少。这是理想的环境,但不行的是,理想环境往往不会出现在现实环境中。为了模拟真实的环境,我建立了第二个测试。这次测试使用跟第一次相同的算法,但测试任务在十个并发线程上执行,以模拟处在压力环境中的服务器同时处理十个请求的情况。这十个请求使用传统的顺利处理方法或Java 8的新API处理。
测试结果
- 排序现在只快了20%
- 过滤现在只快了20%
- 分组现在慢了15%
更高的规模和竞争水平很可能使这些数字进一步下降。原因是在一个多线程的环境中添加线程并不一定能帮助你提高计算效率,是计算机的CPU个数决定了计算效率,而不是线程个数。

结论
虽然这些都是非常强大和易于使用的API,但它们不是银弹。我们仍然需要花费精力去判断何时应该使用它们。如果你事先知道你会做多个处理并行操作,那么考虑使用排队架构,并使并发操作数和你的处理器数量相匹配可能是一>个好主意。这里的难点在于运行时性能将依赖于实际的硬件体系结构和服务器所处的压力情况。你可能只有在压力测试或者生产环境中才能看到代码的运行时性能,使之成为一个“易编码,难调试”的经典案例。
Java 8的新并行API - 魅力与炫目背后的更多相关文章
- Java笔记 - 线程与并行API
一.线程简介 1.线程与进程 每个进程都具有独立的代码和数据空间,进程间的切换会有较大的开销.线程是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开 ...
- java JDK8 学习笔记——第11章 线程和并行API
第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...
- Java 9中新的货币API
译文出处: Java译站 原文出处:Michael Scharhag JSR 354定义了一套新的Java货币API,计划会在Java 9中正式引入.本文中我们将来看一下它的参考实现:JavaMo ...
- Java 8 (11) 新的日期和时间API
在Java 1.0中,对日期和时间的支持只能依赖java.util.Date类.这个类只能以毫秒的精度表示时间.这个类还有很多糟糕的问题,比如年份的起始选择是1900年,月份的起始从0开始.这意味着你 ...
- java 8中新的日期和时间API
java 8中新的日期和时间API 使用LocalDate和LocalTime LocalDate的实例是一个不可变对象,它只提供了简单的日期,并不含当天的时间信息.另外,它也不附带任何与时区相关的信 ...
- [转] Java 8的新特性
简介 毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和JVM等方面的十多个新特性.在本文中我们将学习这些新特性,并用实际的例子 ...
- Java 8 中的 Streams API 详解
为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...
- Java 8的新特性—终极版
作者:杜琪[译] 原文链接:http://www.jianshu.com/p/5b800057f2d8 1. 简介 毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本 ...
- Java 8 的新特性和改进总览
这篇文章是对Java 8中即将到来的改进做一个面向开发者的综合性的总结,JDK的这一特性将会在2013年9月份发布. 在写这篇文章的时候,Java 8的开发工作仍然在紧张有序的进行中,语言特新和API ...
随机推荐
- 【转】Android布局优化之ViewStub
ViewStub是Android布局优化中一个很不错的标签/控件,直接继承自View.虽然Android开发人员基本上都听说过,但是真正用的可能不多. ViewStub可以理解成一个非常轻量级的Vie ...
- “代理XP”组件已作为此服务器安全配置的一部分被关闭的解决办法
代理XP”组件已作为此服务器安全配置的一部分被关闭.系统管理员可以使用sp_configure来启用“代理XP”.有关启用“代理XP”的详细信息,请参阅SQL Server联机丛书中的“外围应用配置器 ...
- MySQL查询及删除重复记录的方法
查询及删除重复记录的方法(一)1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select * from peoplewhere peopleId in (select p ...
- git .gitignore 文件 解决二进制文件冲突问题
.gitignore 主要是添加 忽略文件 .最近团队开发经常出现 UserInterfaceState.xcuserstate 冲突,打开发现是二进制文件 ,没法解决冲突. 只好 rm -rf 之 ...
- JavaScript过滤除连续的数字
if (!Array.prototype.forEach) { Array.prototype.forEach = function (callback, thisArg) { var T, k; i ...
- 39. Volume Rendering Techniques
Milan Ikits University of Utah Joe Kniss University of Utah Aaron Lefohn University of California, D ...
- 采用ODAC,ODBC连接Oracle【转】
采用ODAC,ODBC连接Oracle 在没有装oracle的环境中,偶尔会需要访问数据库(Word文档查看数据,开发项目运行等等),简单介绍我用过的方案. 一:ODAC 1.介绍.ODAC,全称:o ...
- 迁移SQL SERVER 数据库实例
由于某些原因,需要将2个数据库实例合并为1个,也就是说要把其中的一台迁移到另外一台上面. 背景介绍 :下面的B,C代表2个实例,要把B中相关东西迁移到C实例上面.其中B上面有一部分的同步是从另外一台服 ...
- 关于mvc、webapi中get、post、put、delete的参数
webapi中post提交的数据必须是一个类,get提交的数量无所谓 多种参数get时,参数名不能相同: 在能通过c#的校验的前提下,参数名.参数数量不能全完相同 public string Get( ...
- 没有 RunInstallerAttribute.Yes 的公共安装程序。在 C:/Program/xx.exe 程序集中可能可以找到
今天在装服务的时候,装了半天总是提示 没有 RunInstallerAttribute.Yes 的公共安装程序.在 C:/Program/xx.exe 程序集中可能可以找到“Yes”属性. 才发现同事 ...