39

Я слышал, что Java 8 предоставляет множество утилит для параллельных вычислений. Поэтому мне интересно, что является самым простым способом для параллелирования данного цикла?Java 8: Parallel FOR loop

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); 
    } 
} 

ответ

44

Читайте также: streams, все они новые ярости.

Обратите особенно пристальное внимание к биту о параллельности:

«Обработка элементах с явным для цикла по своей сути последовательного Streams облегчает параллельное выполнение, рефрейминг вычисления как трубопровод агрегированных операций, а не. как обязательные операции над каждым отдельным элементом. Все операции с потоками могут выполняться либо последовательно, либо параллельно ».

Итак, для повторения нет параллельных циклов, они по сути являются серийными. Однако потоки могут выполнять эту работу. Взгляните на следующий код:

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

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

Это потрясающе. Спасибо –

+0

Эх, я дал точно такой же ответ ... – fge

+4

Обратите внимание, что параллельные потоки имеют накладные расходы: он не всегда повышает производительность по последовательному потоку (или нормальному для каждого). –

13

Это было бы с помощью Stream:

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

Я подозреваю, что Collector может быть использован для большего эффекта здесь, так как вы используете параллельную коллекцию.

+0

Ну, после посоветуйте, я теперь могу прочитать лямбда-выражения, как а также знаю некоторые детали потоков, а также;) – dosdebug

4

Более элегантный или функциональное решение будет только с помощью Коллекторы 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. Чтобы получить полные преимущества параллельного потока, количество серверов будет большим и не будет задействовано ввода-вывода, чисто данных обработка в этих функциях ()

Пожалуйста, обратитесь к Коллекторы Javadoc на http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toConcurrentMap

-3

с помощью моего 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); 
     } 
    }); 
}  
Смежные вопросы