10-使用jdk8提供的lambda进行并行计算

 

10-使用jdk8提供的lambda进行并行计算

本节来了解创建线程的最后一种方式:使用Lambda表达式实现。

Lambda表达式是jdk8中所实现的一个新特性,称之为函数式编程,也是一个非常强大的功能。

Lambda表达式有非常多的好处,当然了,它也有坏处,我们这里简单提几点它的好处,就是,使用Lambda表达式的代码看上去会更加的简洁,另外就是,实现起来会更加的方便,然后,再就是,它对并发的支持是非常好的,使用Lambda表达式写出来的代码可能性能是非常高的,我们本节主要是了解使用Lambda表达式实现并发,或者说,让它用多线程去干一件事。

Lambda表达式对并发的支持是非常好的,使用Lambda表达式写出来的代码性能是非常高的,我们本节主要是了解使用Lambda表达式来实现一个并发,或者说,让它用多线程去干一件事。

使用Lambda表达式做一个并行的求和的运算,求一个集合中的值求和,比如从一个文本中读取大量的数值,然后放到一个集合中,然后计算这个集合中的值求和。

我们首先获取它的并发流

10-使用jdk8提供的lambda进行并行计算

10-使用jdk8提供的lambda进行并行计算

stream()是普通的,parallelStream()是一个并行的流,Java收集器里面有一个parallel收集器,这个收集器是并发的,就是说,你扔垃圾和扫地是同时进行的,非常强大。下面要怎么办呢?

10-使用jdk8提供的lambda进行并行计算

这里报错了。

我们要求和,求和,这里面有一个sum()方法,sum()方法是int的方法,所以我们要

10-使用jdk8提供的lambda进行并行计算

把这个stream,这个流转成一个int stream,我们可以使用mapToInt()方法。

10-使用jdk8提供的lambda进行并行计算

这里面我们只要传入一个ToIntFunction就可以了。怎么ToIntFunction呢?我们随便定义变量,比如本例定义变量a,让a指向a

10-使用jdk8提供的lambda进行并行计算

这是什么意思呢?就是把这里面迭代出来的每一个元素,让它的值等于a然后在放到一个新的stream中去,那么mapToInt所返回的就是一个IntStream

10-使用jdk8提供的lambda进行并行计算

mapToInt是一个函数式接口,它的返回值就是一个IntStream,通过IntStream的sum方法,就可以把转换出来的IntStream里面的元素进行求和。

10-使用jdk8提供的lambda进行并行计算

这就是一个加法的计算过程。

下面我们就用一个主函数来调用它就可以了。

10-使用jdk8提供的lambda进行并行计算

这样就构造了一个长度为4,元素为10、20、30、40的一个List集合,然后,下面我们就来调用add就可以了。

10-使用jdk8提供的lambda进行并行计算

这样似乎并看不出来它是一个并行执行的,既然看不出来,那么,我们就来看一下,

10-使用jdk8提供的lambda进行并行计算

先把它给扔掉,一会我们再来看这段代码。

10-使用jdk8提供的lambda进行并行计算

先来验证它是并行执行的而不是串行执行的,其实它底层所用到的原理是我们后面要讲的ForkJoin框架,它底层所依赖的就是ForkJoin框架,它是分而治之的思想。分开,分别计算完之后,然后再合并到一块,类似于Hadoop里面的MapReduce。我们就让它来并行的打印一下values集合中的元素,如果它是串行的话,那么,肯定是按照顺序打印的,如果是并行执行的话,那么,打印出来肯定是乱序的。首先还是先获得parallelStream

10-使用jdk8提供的lambda进行并行计算

然后,在这里面我们就可以调用,让它不停的去打印,叫做forEach()

10-使用jdk8提供的lambda进行并行计算

那么,这里面如何去写参数呢?我们就可以调用System的out对象的println方法

10-使用jdk8提供的lambda进行并行计算

这就是来打印values集合中的元素的值

10-使用jdk8提供的lambda进行并行计算

我们来运行代码

10-使用jdk8提供的lambda进行并行计算

我们发现打印出来的值是乱序的。

我们再来验证Stream流是普通的流,它不是并行执行的,

10-使用jdk8提供的lambda进行并行计算

这也就恰恰证明了parallelStream是并行执行的,有同学可能会说,现在是并行执行了,但是我就是想让它按原序输出,该怎么办呢?可以使用forEachOrdered

10-使用jdk8提供的lambda进行并行计算

现在已经验证了Lambda表达式实现并行执行,也就是说我们创建线程使用Lambda表达式已经执行完毕了,其实本节的内容也就结束了。

这里在给大家去普及一下,刚刚大家可能觉得刚刚写的是不是Java代码呀,

10-使用jdk8提供的lambda进行并行计算

这段代码,

10-使用jdk8提供的lambda进行并行计算

这个地方是什么意思呢?大家可以这么理解,把parallelStream理解成一个Iterator,但是parallelStream比Iterator要强大的多,因为parallelStream就是支持并行的,Iterator只能串行化执行,为什么称之为parallelStream为流呢?跟迭代器是一样的,我们知道,迭代器每next一下,这个过程是不可逆的,parallelStream同样也是。

mapToInt()是把这个Stream

10-使用jdk8提供的lambda进行并行计算

转换成了一个IntStream

10-使用jdk8提供的lambda进行并行计算

也就是说,转换后的IntStream中就全是int了,int就可以进行相加了。那么,是如何从Stream转到IntStream的呢?它没迭代出来一个

10-使用jdk8提供的lambda进行并行计算

可以随便起一个名字,就类似于迭代器中的,增强for循环就是迭代器的原理,

10-使用jdk8提供的lambda进行并行计算

增强for循环中,此处的i就是随便起的名字。

10-使用jdk8提供的lambda进行并行计算

这里面的i其实,也是同增强for循环中变量(上例子中的i)是同样的道理的,但是我们知道

10-使用jdk8提供的lambda进行并行计算

我们要迭代这个values,它本身就是一个Integer类型,所以,在JDK8中,它能够类型的猜测,就是,它能够更强大的去猜,它能够猜测出来这个类型,这个更强大的能力也是JDK8的一个特性,它能够把类型给猜出来,

10-使用jdk8提供的lambda进行并行计算

就像之前泛型刚出来的时候,

10-使用jdk8提供的lambda进行并行计算

我们之前在创建的过程中,前后的尖括号中都必须要写清楚对象的类型。

我们似乎发现,自从更新了JDK只会,后面的尖括号中我们反而不需要写对象的类型了,写了反而显得麻烦,这就是一个类型的猜测。

10-使用jdk8提供的lambda进行并行计算

到了Lambda表达式中,类型的猜测就变得更加的彻底了

10-使用jdk8提供的lambda进行并行计算

把它转换成一个int类型

10-使用jdk8提供的lambda进行并行计算

转换完之后,随便起一个名字

10-使用jdk8提供的lambda进行并行计算

就是说,后面这个,也不是说起名字,它就是拿前面的值,其实后面(本例中的i)拿的就是前面(本例中的i)的值,当然了,咱们可以对拿到的值进行一些操作

10-使用jdk8提供的lambda进行并行计算

10-使用jdk8提供的lambda进行并行计算

 

就是说

10-使用jdk8提供的lambda进行并行计算

这里是迭代出来的结果,然后,

10-使用jdk8提供的lambda进行并行计算

这个就是把前面迭代出来的结果可以进行一些处理,如果我们不对迭代出来的结果进行处理,那么它还是原来迭代出来的结果,如果我们对迭代出来的结果进行处理,那么,这里就写处理的表达式。

当然了,我们这里可以写成String,

10-使用jdk8提供的lambda进行并行计算

那么,每次迭代出来的就是String

10-使用jdk8提供的lambda进行并行计算

它自动才出来了迭代出来的类型是String,我们想让把String放到一个int中去,显然这样写是不行的

10-使用jdk8提供的lambda进行并行计算

我们可以通过这个方法去转换一下

10-使用jdk8提供的lambda进行并行计算

这样也是可以的。

这就是关于关于mapToInt()。

这就是关于Lambda表达式并行的来处理一个集合

10-使用jdk8提供的lambda进行并行计算

关于Lambda表达式,我们就说到这里。

10-使用jdk8提供的lambda进行并行计算

关于创建线程,这里一共提了8种方式

如果感兴趣,可以去了解一下quartz(定时器框架)。