Java 8:并行FOR循环

Joe*_*ner 60 java concurrency for-loop java.util.concurrent concurrent-programming

我听说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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 83

阅读溪流,他们都是新的愤怒.

特别注意关于并行性的一点:

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

所以回顾一下,没有并行的for循环,它们本质上是串行的.然而Streams可以完成这项工作.看看下面的代码:

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

    servers.parallelStream().forEach((server) -> {
        serverData.put(server.getIdentifier(), server.fetchData());
    });
Run Code Online (Sandbox Code Playgroud)

  • 请注意,并行流有一个开销:它并不总能提高串行流的性能(或者每个都是正常的). (5认同)
  • @SonuMishra,否.并行流尝试在处理器上使用多个内核. (3认同)
  • 如何使用.parallelStream()处理线程?它是否使用任何内部线程池? (2认同)
  • 如果我们在服务器中有一百万个元素怎么办?这会产生一百万个并行流吗? (2认同)

fge*_*fge 18

那将使用Stream:

servers.parallelStream().forEach(server -> {
    serverData.put(server.getIdentifier(), server.fetchData());
});
Run Code Online (Sandbox Code Playgroud)

我怀疑在Collector这里可以使用更大的效果,因为你使用并发集合.


zd3*_*333 6

更优雅或功能性的解决方案是使用Collectors toMap或toConcurrentMap函数,这样可以避免为ConcurrentHashMap维护另一个有状态变量,如下例所示:

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

注意: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上的收集器javadoc.


Con*_*ngo 6

复制“n”粘贴的简单示例(上面的示例使用的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);
});
Run Code Online (Sandbox Code Playgroud)

控制台输出。由于所有内容都并行执行,因此顺序可能会有所不同:

Item1
Item2
Run Code Online (Sandbox Code Playgroud)

.parallelStream()方法是在Java v8. 这个例子是用JDK v1.8.0_181.