Manejo de hilos y procesos en paralelo
En muchas ocasiones nos enfrentamos con el problema de tener que manejar un flujo que internamente tiene muchos procesos, cada proceso interno tiene un tiempo de ejecución se más de 3 segundos y el flujo maneja normalmente volumenes de más de 100 procesos por lote.
Para esta casuistica lo que queremos es que nuestro sistema pueda ejecutar los procesos pero que se tome el menor tiempo posible, es decir, si para este caso nosotros recorremos cada registro de nuestra lista y ejecutamos el proceso tomando como base que cada registro se va a demorar 4 segundos; el proceso final se tomaria al rededor de 7 minutos en terminar toda la operación.
Lo que queremos es aprovechar al maximo los recursos de la maquina y por eso lo que podemos hacer crear un proceso en el cual a travez de los hilos disponibles de nuestra maquina podamos ejecutar en paralelo el maximo de procesos que podamos.
Aplicando los conceptos mensionados pudimos mejorar los tiempos de respuesta de este proceso de 7 minutos a 52 segundos, a continuación dejamos el codigo para que puedas implementarlo en tus procesos
package com.project.core.service;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@Service
@EnableAsync
public class Developer {
public boolean test() {
System.out.println("avalidableProcessors " + Runtime.getRuntime().availableProcessors());
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<Integer> records = IntStream.range(0, 100).boxed().collect(Collectors.toList());
List<Future<String>> futures = records.parallelStream()
.map(record -> (Callable<String>) () -> executor(record))
.map(executor::submit)
.collect(Collectors.toList());
// Wait for all tasks to complete and print their results
futures.forEach(future -> {
try {
System.out.println(future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
});
executor.shutdown();
return true;
}
public String executor(Integer record) throws InterruptedException {
long startTime = System.currentTimeMillis();
// Simulate processing time between 1 and 6 seconds
//Thread.sleep((long) (Math.random() * 5000 + 1000));
Thread.sleep(4000L);
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
return "Processed record " + record + " in " + (duration/1000) + " seconds.";
}
}