sentencias sentencia para mejorado loop infinito for espaƱol ejemplos doble condicion con bucles java for-loop concurrency java.util.concurrent concurrent-programming

sentencia - Java 8: ciclo FOR paralelo



sentencia for en java eclipse (5)

Escuché que Java 8 proporciona muchas utilidades con respecto a la computación concurrente. Por lo tanto, me pregunto cuál es la forma más simple de paralelizar el ciclo for dado.

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


Ejemplo simple para copiar y pegar (los ejemplos anteriores usan la clase Server que es una clase personalizada escrita por el 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); });

Salida de consola. El orden podría variar ya que todo se ejecuta en paralelo:

Item1 Item2

El método .parallelStream() se introdujo en Java v8 . Este ejemplo fue probado con JDK v1.8.0_181 .


Eso sería usar un Stream :

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

Sospecho que un Collector se puede utilizar para un mayor efecto aquí, ya que utiliza una colección concurrente.


Lea sobre las streams , son toda la nueva rabia.

Presta especial atención al bit sobre paralelismo:

"El procesamiento de elementos con un bucle for explícito es inherentemente serial. Los flujos facilitan la ejecución paralela al reenmarcar el cálculo como una tubería de operaciones agregadas, en lugar de operaciones imperativas en cada elemento individual. Todas las operaciones de flujos pueden ejecutarse en serie o en paralelo. "

En resumen, no hay bucles for paralelos, son inherentemente seriales. Sin embargo, las transmisiones pueden hacer el trabajo. Echa un vistazo al siguiente código:

Set<Server> servers = getServers(); Map<String, String> serverData = new ConcurrentHashMap<>(); servers.parallelStream().forEach((server) -> { serverData.put(server.getIdentifier(), server.fetchData()); });


Una solución más elegante o funcional será simplemente usar Collectors toMap o toConcurrentMap, que evitan mantener otra variable con estado para ConcurrentHashMap, como el siguiente ejemplo:

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

Nota: 1. Esas interfaces funcionales ( Server::getIdentifier or Server::fetchData ) no permiten lanzar una excepción marcada aquí, 2. Para obtener todos los beneficios del flujo paralelo, el número de servidores sería grande y no hay I / O involucrado, puramente procesamiento de datos en esas funciones ( getIdentifier, fetchData )

Consulte Collector javadoc en http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toConcurrentMap


usando mi Paralelo. Para, su código podría ser similar al siguiente,

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