Estoy tratando de procesar el siguiente código usando subprocesos múltiples en el nivel de pedido.
List<String> orders = Arrays.asList("order1", "order2",
"order3", "order4", "order1");
Ejecución secuencial actual:
orders.stream().forEach(order -> {
rules.forEach(rule -> {
finalList.add(beanMapper.getBean(rule)
.applyRule(createTemplate.apply(getMetaData.apply(rule), command),
order));
});
});
He intentado usar:
orders.parallelStream().forEach(order -> {}} // code snippet.
Pero está cambiando las reglas . Para cada orden (regla -> {}} .
Por ejemplo:
Entrada:
List<String> orders = Arrays.asList("order1", "order2",
"order3", "order4", "order1");
List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
Rendimiento esperado:
order1 with rule1, rule2, rule3
order2 with rule1, rule2, rule3
Salida real con parallelStream()
:
order1 with rule3, rule1, rule2
order1 with rule2, rule1, rule3
No me preocupa el orden de las órdenes , pero me preocupa el orden de las reglas . Las órdenes pueden procesarse en cualquier orden, pero las reglas deben ejecutarse en el mismo orden para cada orden.
Por favor ayuda.
java
multithreading
java-8
java-stream
Mayank Bisht
fuente
fuente
Agrega elementos a
finalList
diferentes hilos al mismo tiempo. Esto está causando resultados mixtos al aplicar reglas a diferentes órdenes (las reglas no se agrupan por sus órdenes).Puede solucionarlo creando una lista temporal para cada uno
order
y luego fusionando sincrónicamente todas las listas temporales en afinalList
.Así es como puede hacerlo utilizando Stream-API (Java 9+):
Nota:
Collectors.flatMapping()
se usa aquí en lugar de una simpleflatMap
asignación plana sincrónica durante la recopilación de secuencias.Java 8 analógico:
fuente
beanMapper.getBean(rule) .applyRule(createTemplate.apply(getMetaData.apply(rule), command), order)
no es una función pura, por lo que no se puede usar en paralelo. Intenta eliminar todos los efectos secundarios;ConcurrentModificationException
stack trace puede ayudar a localizarlos.esto funcionara?
Salida
fuente
Si ese es el caso, no hay espacio para el paralelismo real.
Cuando
y
son las únicas ejecuciones válidas para 2 pedidos y 2 reglas,
y
se considera inválido, eso no es paralelismo, solo aleatorización de
order
s, presumiblemente sin ganancia. Si está "aburrido" deorder1
venir primero todo el tiempo, puede barajar la lista, pero eso es todo:Ni siquiera es necesaria la transmisión, solo dos bucles anidados. Prueba: https://ideone.com/qI3dqd
Respuesta original
No, no lo hace. La
order
s puede superponerse, perorule
se mantiene el orden de s para cada orden. ¿Por qué un no paraleloforEach
haría algo más?Código de ejemplo:
Prueba: https://ideone.com/95Cybg
Ejemplo de salida:
El orden de
order
s es mixto, pero losrule
s siempre son 1-2-3. Creo que su salida simplemente ocultó los emparejamientos (en realidad no mostró cómo se generó).Por supuesto, puede extenderse con algunos retrasos, por lo que el procesamiento de
order
s realmente se superpondrá:Prueba: https://ideone.com/cSFaqS
Ejemplo de salida:
Esto puede ser algo que has visto, solo que sin la
orderx
parte. Con losorder
s visibles, se puede rastrear querule
siguen llegando como 1-2-3, pororder
. Además, su lista de ejemplo conteníaorder1
dos veces, lo que seguro no ayudó a ver lo que estaba sucediendo.fuente
order
s no pueden superponerse (¿sonrule
s afirmativos tal vez y existen en un número limitado de copias, tal vez solo una?). Pero, en general, no hay paralelismo sin que las cosas funcionen en paralelo, ese es el punto central del paralelismo después de todo.Si no te importa probar la biblioteca de terceros. Aquí hay una muestra con mi biblioteca: abacus-util
E incluso puede especificar el número de hilo:
El orden de
rule
se mantendrá.Por cierto, dado que está en flujo paralelo, el fragmento de código
...finalList.add(...
probablemente no funcionará. Creo que es mejor recopilar el resultado para enumerarlo:también es factible incluso si desea mantener el orden
order
por algún motivo más adelante:fuente