使用Java 8和lambda,可以很容易地将集合作为流进行迭代,也很容易使用并行流。docs中的两个示例,第二个示例使用parallelStream:
myShapesCollection.stream()
.filter(e -> e.getColor() == Color.RED)
.forEach(e -> System.out.println(e.getName()));
myShapesCollection.parallelStream() // <-- This one uses parallel
.filter(e -> e.getColor() == Color.RED)
.forEach(e -> System.out.println(e.getName()));
只要我不关心顺序,使用并行会一直有益吗?有人会认为,更快地将工作划分到更多的内核上。
还有其他考虑事项吗?什么时候应该使用并行流,什么时候应该使用非并行?
(问这个问题引发了关于如何以及何时使用并行流的讨论,不是因为我认为始终使用并行流是一个好主意。)
A parallel stream has a much higher overhead compared to a sequential one. Coordinating the threads takes a significant amount of time. I would use sequential streams by default and only consider parallel ones if
I have a massive amount of items to process (or the processing of each item takes time and is parallelizable)
I have a performance problem in the first place
I don't already run the process in a multi-thread environment (for example: in a web container, if I already have many requests to process in parallel, adding an additional layer of parallelism inside each request could have more negative than positive effects)
在您的示例中,无论如何,性能都将受到对的同步访问的驱动System.out.println()
,并且使此过程并行不会产生影响,甚至不会产生负面影响。
此外,请记住,并行流并不能神奇地解决所有同步问题。如果过程中使用的谓词和函数使用了共享资源,则必须确保所有内容都是线程安全的。尤其是副作用,如果并行使用,您确实要担心。
无论如何,不要猜测!只有度量会告诉您并行性是否值得。
好答案。我还要补充一点,如果您要处理大量项目,那只会增加线程协调问题;仅当每个项目的处理需要时间并且可并行化时,并行化才有用。
@WarrenDew我不同意。Fork / Join系统将简单地将N个项目分为例如4个部分,并依次处理这4个部分。然后将减少这4个结果。如果大量确实是巨大的,即使对于快速的单元处理,并行化也是有效的。但与往常一样,您必须进行衡量。
我有一个实现
Runnable
要调用start()
以用作它们的对象的集合Threads
,是否可以将其更改为在.forEach()
并行化中使用java 8流?然后,我可以将线程代码从类中剥离出来。但是有什么缺点吗?@JBNizet如果顺序处理4个部分,那么它是并行处理还是顺序知道没有区别?请澄清
@Harshana他显然意味着这4个部分中每个部分的元素将被顺序处理。但是,零件本身可以同时处理。换句话说,如果您有几个可用的CPU内核,则每个部分都可以独立于其他部分在其自己的内核上运行,同时依次处理其自身的元素。(注意:我不知道,如果这是并行Java流的工作方式,我只是想弄清楚JBNizet的意思。)