Java 8:并行FOR循环


69

我听说Java 8提供了许多有关并发计算的实用程序。因此,我想知道并行化给定for循环的最简单方法是什么?

public static void main(String[] args)
{
    Set<Server> servers = getServers();
    Map<String, String> serverData = new ConcurrentHashMap<>();

    for (Server server : servers)
    {
        String serverId = server.getIdentifier(); 
        String data = server.fetchData();

        serverData.put(serverId, data);
    }
}

Answers:


97

上阅读,这些都是新的流行。

特别注意并行性:

“具有显式for循环的处理元素本质上是串行的。流通过将计算重新格式化为聚合操作的流水线而不是对每个单独元素的命令性操作来促进并行执行。所有流操作都可以串行或并行执行。 ”

综上所述,没有并行的for循环,它们本质上是串行的。但是,流可以完成这项工作。看下面的代码:

    Set<Server> servers = getServers();
    Map<String, String> serverData = new ConcurrentHashMap<>();

    servers.parallelStream().forEach((server) -> {
        serverData.put(server.getIdentifier(), server.fetchData());
    });

7
请注意,并行流有开销:它并不能总是比串行流(或每个流的正常)提高性能。
Mark Rotteveel 2014年

2
如何使用.parallelStream()处理线程?是否使用任何内部线程池?
Ashika Umanga Umagiliya

2
如果服务器中有一百万个元素怎么办?这会创建一百万个并行流吗?
Sonu Mishra'7

4
@SonuMishra,否。并行流尝试利用处理器上的多个内核。
阿比吉斯(Abhijith Madhav)

我认为您可以更加清楚地知道,可以/将并行调用forEach方法的回调
Alexander Mills,

21

那将使用Stream

servers.parallelStream().forEach(server -> {
    serverData.put(server.getIdentifier(), server.fetchData());
});

我怀疑Collector这里可以使用a产生更大的效果,因为您使用并发集合。


好吧,根据您的建议,我现在可以阅读lambda表达式,也可以了解流的一些详细信息;)
SSC 2014年

9

更加优雅或实用的解决方案将仅使用Collector的toMap或toConcurrentMap函数,避免为ConcurrentHashMap维护另一个有状态变量,如下例所示:

final Set<Server> servers = getServers();
Map<String, String> serverData = servers.parallelStream().collect(
    toConcurrentMap(Server::getIdentifier, Server::fetchData));

注意:1.这些功能接口(Server::getIdentifier or Server::fetchData)此处不允许进行抛出检查的异常,2.为了获得并行流的全部好处,服务器数量将很大,并且不涉及I / O,纯粹是其中的数据处理功能(getIdentifier, fetchData

请参考http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toConcurrentMap上的Collector Javadoc。


4

复制n'paste的简单示例(上面的示例使用的类Server是OP编写的自定义类):

import java.io.Console;
import java.util.ArrayList;

ArrayList<String> list = new ArrayList<>();
list.add("Item1");
list.add("Item2");
list.parallelStream().forEach((o) -> {
    System.out.print(o);
});

控制台输出。随着一切并行执行,顺序可能会有所不同:

Item1
Item2

.parallelStream()方法在中引入Java v8。此示例已通过测试JDK v1.8.0_181


-6

使用我的Parallel.For,您的代码可能如下所示,

public staic void main(String[] args)
{
    Set<Server> servers = getServers();
    Map<String, String> serverData = new ConcurrentHashMap<>();

    Parallel.ForEach(servers, new LoopBody<Server>()
    {
        public void run(Server server)
        {
             String serverId = server.getIdentifier(); 
             String data = server.fetchData();

             serverData.put(serverId, data);
        }
    });
}     

那是C#,而不是Java
Benjsoft
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.