精通lambda表达式 Java多核编程[Mastering Lambdas: Java Programming in a Multicore]pdf

图书网 2020年10月8日21:10:58
评论
1.6K

精通lambda表达式 Java多核编程[Mastering Lambdas: Java Programming in a Multicore] 作者:(美) 那夫特林(Naftalin,M. )

精通lambda表达式 Java多核编程[Mastering Lambdas: Java Programming in a Multicore] 出版社:清华大学出版社

精通lambda表达式 Java多核编程[Mastering Lambdas: Java Programming in a Multicore] 内容简介

lambda表达式指南 《精通lambda表达式:Java多核编程》介绍Java SE 8中与lambda相关的特性是如何帮助Java迎接下一代并行硬件架构的挑战的。本书讲解了如何编写lambda、如何在流与集合处理中使用lambda,并且提供了完整的代码示例。你将学习如何通过lambda表达式充分利用当今多核硬件所带来的性能改进。

主要内容:

● 为何需要lambda,它将如何改变Java编程

● lambda表达式语法

● 流与管道的基本操作

● 使用收集器与汇聚来终止管道

● 创建流

● 分割迭代器、fork/join框架与异常

● 使用微基准测试检查流的性能

● 使用默认方法演化API

精通lambda表达式 Java多核编程[Mastering Lambdas: Java Programming in a Multicore] 目录

前言

第1章 走进新生代的Java

1.1 从外部迭代到内部迭代

1.2 从集合到流

1.3 从串行到并行

1.4 组合行为

1.5 小结

第2章 Javalambda表达式的基础知识

2.1 lambda表达式的定义

2.2 lambda与匿名内部类

2.3 变量捕获

2.4 函数式接口

2.5 使用lambda表达式

2.6 方法与构造器引用

2.7 类型检查

2.8 重载解析

2.9 小结

第3章 流与管道介绍

3.1 流基础

3.2 剖析管道

3.3 小结

第4章 终止流:收集与汇聚

4.1 使用收集器

4.2 剖析收集器

4.3 编写收集器

4.4 汇聚

4.5 小结

第5章 起始流:源与分割迭代器

5.1 创建流

5.2 分割迭代器与Fork/Join

5.3 异常

5.4 示例说明:递归grep

5.5 小结

第6章 流的性能

6.1 微基准度量

6.2 选择执行模式

6.3 流的特性

6.4 排序

6.5 有状态操作与无状态操作

6.6 装箱与拆箱

6.7 分割迭代器性能

6.8 收集器性能

6.9 小结

第7章 使用默认方法演化APl

7.1 使用默认方法

7.2 抽象类的角色是什么

7.3 默认方法的语法

7.4 默认方法与继承

7.5 接口中的静态方法

7.6 小结

本书总结

精通lambda表达式 Java多核编程[Mastering Lambdas: Java Programming in a Multicore] 精彩文摘

Java 8可谓Java语言历史上变化*大的一个版本,这体现在语言、库与虚拟机协调一致的变化上。其承诺要改变我们思考Java程序执行的方式,并且让语言适合于不久之后将要到来的在大规模并行硬件上的使用。不过相对于如此重要的创新,语言的实际变化却显得有些微不足道。这些表面上的微小变化到底是如何产生这种巨大的差别的呢?我们为何要改变Java中已经使用了这么多年(实际时间比这还要长)的编程模型呢?本章将会谈及这种模型的限制,同时还会介绍Java 8中lambda相关的特性是如何促使Java不断演进以满足新一代硬件架构的挑战的。

1.1 从外部迭代到内部迭代

首先来看一段简单的代码,这段代码会迭代一个包含着可变对象的集合,并对集合中的每个对象调用一个方法。如下代码片段会构造一个java.awt.Point(Point是个便捷、简单的库类,包含了一对(x,y)坐标)对象的集合。接下来,代码会对集合进行迭代,并对每个Point沿着x与y轴各平移1个单位的距离。

Point(2, 3));

for (Point p:pointList) {

p.translate(1, 1);

}

在Java 5引入for-each循环前,我们可以像下面这样编写循环:

for (Iterator pointItr = pointList.iterator();

pointItr.hasNext(); ) {

((Point) pointItr.next()).translate(1, 1);

}

下面这种写法会更清晰一些(不过并不推荐这种写法,因为它扩大了pointItr的作用域):

Iterator pointItr = pointList.iterator();

while (pointItr.hasNext()) {

((Point) pointItr.next()).translate(1, 1);

}

上述代码中,pointList会创建一个Iterator对象,接下来我们通过该对象依次访问pointList中的元素。这个版本的代码还是非常有意义的,因为时至今日这正是Java编译器生成的用于实现for-each循环的代码。对于我们来说,其关键在于访问pointList中元素的顺序是由Iterator控制的——我们无法改变这一点。比如,针对ArrayList的Iterator会按照先后顺序返回列表中的元素。

这么做为什么会有问题呢?毕竟,Java Collections Framework是在1998年设计的,看起来按照这种方式来指定列表元素的访问顺序是合情合理的。从那时起发生了什么变化呢?

部分原因在于硬件在不断演进。长久以来,工作站与服务器都配有多个处理器,不过在设计Java Collections Framework框架的1998年与个人电脑中首个双核处理器出现的2005年之间,芯片设计领域的革命爆发了。40年来处理器速度以指数级别增长的趋势停止了,这是由于如下不可避免的事实造成的:信号泄漏、散热不充分,以及虽然到达了光速,但数据无法足够快地跨越芯片以实现更快的处理器速度的增长。

不过虽然存在时钟频率的限制,芯片组件的密度还在持续增加。因此,既然无法提供6 GHz的核,芯片厂商转而开始提供双核处理器,每个核运行于3 GHz。这种趋势还在持续,目前还没有终止的迹象;在Java 8发布之时(2014年3月),四核处理器已经成为主流,八核处理器也已经出现在硬件市场上,而专业服务器早就在每个处理器中放置了几十个核。趋势很明显,不适应这种状况的任何编程模型都会在与适应这种状况的模型的竞争中败下阵来。适应意味着向开发者提供一种可访问的方式,使之能够将多个任务分发到多个核上并行执行,从而利用多核的处理能力。另一方面,不适应意味着默认情况下Java程序会被绑定到单个核上,相对于那些能够帮助用户并行运行代码的语言来说,这会极大地降低程序的运行速度。

本节一开始的代码已经表明了改变的必要性,代码一次只能根据迭代器指定的顺序访问一个列表元素。集合处理并非程序员执行的唯一一个处理器密集的任务,不过它却是*重要的任务之一。Java循环构建中所用的迭代模型会强制顺序处理集合元素,如果对运行时*迫切的需求刚好相反(至少要考虑性能因素):将处理分发到多个核上,那么这就会产生严重的问题。第6章将会谈到,并不是每个问题都会从并行化中获益,不过*好的情况则是程序的加速几乎与核心数量线性相关。

1.1.1 内部迭代

在考虑将迭代的顺序模型应用到真实世界的场景中时就会发现其侵入性变得非常明显。如果有人通过如下指令让你邮寄一些信件——“重复如下动作:如果还有信件,那么按照收件人姓氏的字母表顺序取出下一个,然后将其放到邮箱中”,那么你可能会觉得他这么说太啰嗦了。你知道在这个任务中顺序并不重要,无论是顺序执行还是并行执行都可以,只不过不要遗漏信件即可。这时,你会觉得在存在更好策略的情况下,外部迭代导致集合只能连续并且按照固定顺序处理元素的做法实在是太低效了。

实际上,对于这个现实任务来说,你只需要知道每封信件都要邮寄出去即可;到底该怎么做取决于你自己。同样,我们应该告诉集合应该对它们所包含的每一个元素采取什么动作,而不是像外部迭代那样指定怎么做。如果能够做到这一点,那么代码会变成什么样子呢?集合只需要公开一个方法来接受“做什么”,也就是说对每一个元素要执行什么任务;这个方法的一个显而易见的名字就是forEach。借助于它,我们可以像下面这样替换掉本节一开始的迭代代码:

pointList.forEach(/*translate the point by (1,1)*/);

在Java 8之前,这个建议看起来会很奇怪,因为java.util.List(pointList的类型)并没有forEach方法,作为一个接口,我们也无法向其添加方法。不过,第7章将会看到Java 8通过引入非抽象接口方法解决了这一问题。

新方法Collection.forEach(实际上是由Collection从其父接口Iterable继承的)只不过是内部迭代的一个示例,之所以这么说是因为,虽然已经看不到显式的迭代代码,但迭代依旧在内部发生。迭代现在由forEach方法管理,它会对集合中的每个元素应用其行为参数。

从外部迭代到内部迭代的变化看起来很小,只不过是迭代工作跨越了客户端-库的边界。不过,其结果却并不是那么简单。我们所需要的并行工作现在可以定义在集合类中,不必重复写在每一个要迭代集合的客户端方法中。此外,实现上可以自由使用其他技术,比如说延迟加载、乱序执行或是其他方法,从而更快地获得结果。

如果编程模型允许集合库的作者针对每个集合自由选择*佳的批处理实现方式,那么内部迭代就很有必要了。不过要想替换forEach调用中的注释,那么该如何告诉集合方法应对每个元素执行什么任务呢?

图书网:精通lambda表达式 Java多核编程[Mastering Lambdas: Java Programming in a Multicore]pdf

继续阅读

→→→→→→→→→→→→→→→→→→→→查找获取

程序设计

重构 改善既有代码的设计(中文版)pdf

《重构:改善既有代码的设计》(中文版)所提的这些重构准则将帮助你一次一小步地修改你的代码,这就减少了过程中的风险。很快你就会把这些重构准则和其名称加入自己的开发词典中,并且朗朗上口...
程序设计

数据结构 C语言版 第2版pdf

适读人群 :普通高校电子信息大类本科生学习、考研,同时也适合零售和培训。 采用“案例驱动”的编写模式。书中结合实际应用,将各章按照“案例引入——数据结构及其操作——案例分析与实现”...
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: