Java 8: параллельный цикл FOR
Я слышал, что 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);
}
}
4 ответов
Читать далее потоки, Они все новая ярость.
обратите особое внимание на бит о параллелизме:
" обработка элементов с явным for-loop по своей сути является последовательной. Потоки облегчают параллельное выполнение путем рефрейминга вычисления как конвейера агрегатных операций, а не как императивных операций над каждым отдельным элементом. Все операции streams могут выполняться как в последовательном, так и в параллельный."
Итак, чтобы повторить, нет параллельных for-петель, они по своей сути последовательны. Однако потоки могут выполнять эту работу. Взгляните на следующий код:
Set<Server> servers = getServers();
Map<String, String> serverData = new ConcurrentHashMap<>();
servers.parallelStream().forEach((server) -> {
serverData.put(server.getIdentifier(), server.fetchData());
});
Это будет использовать Stream
:
servers.parallelStream().forEach(server -> {
serverData.put(server.getIdentifier(), server.fetchData());
});
Я подозреваю 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
) не разрешает исключение throw checked здесь,
2. Чтобы получить все преимущества параллельного потока, количество серверов было бы большим, и в них нет ввода-вывода, чисто обработка данных функции(getIdentifier, fetchData
)
пожалуйста, обратитесь к коллекционерам javadoc на http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toConcurrentMap
используя мою параллель.Ибо ваш код может выглядеть следующим образом:
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);
}
});
}