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
finalListdiferentes 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
ordery 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 simpleflatMapasignació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;ConcurrentModificationExceptionstack 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
orders, presumiblemente sin ganancia. Si está "aburrido" deorder1venir 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
orders puede superponerse, perorulese mantiene el orden de s para cada orden. ¿Por qué un no paraleloforEachharía algo más?Código de ejemplo:
Prueba: https://ideone.com/95Cybg
Ejemplo de salida:
El orden de
orders es mixto, pero losrules 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
orders realmente se superpondrá:Prueba: https://ideone.com/cSFaqS
Ejemplo de salida:
Esto puede ser algo que has visto, solo que sin la
orderxparte. Con losorders visibles, se puede rastrear querulesiguen llegando como 1-2-3, pororder. Además, su lista de ejemplo conteníaorder1dos veces, lo que seguro no ayudó a ver lo que estaba sucediendo.fuente
orders no pueden superponerse (¿sonrules 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
rulese 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
orderpor algún motivo más adelante:fuente