Solución:
Fork-join le permite ejecutar fácilmente trabajos de dividir y conquistar, que deben implementarse manualmente si desea ejecutarlo en ExecutorService
. En la práctica ExecutorService
generalmente se usa para procesar muchas solicitudes independientes (también conocidas como transacciones) al mismo tiempo, y unirse a la bifurcación cuando desea acelerar un trabajo coherente.
La unión en bifurcación es particularmente buena para recursivo problemas, donde una tarea implica ejecutar subtareas y luego procesar sus resultados. (Esto generalmente se llama “divide y vencerás” … pero eso no revela las características esenciales).
Si intenta resolver un problema recursivo como este usando subprocesos convencionales (por ejemplo, a través de un ExecutorService) terminará con subprocesos atados esperando que otros subprocesos les entreguen resultados.
Por otro lado, si el problema no tiene esas características, no hay ningún beneficio real de usar fork-join.
Referencias:
- Tutoriales de Java: Fork / Join.
- Consejo de Java: Cuándo usar ForkJoinPool vs ExecutorService:
Java 8 proporciona una API más en Executors
static ExecutorService newWorkStealingPool()
Crea un grupo de subprocesos que roban el trabajo utilizando todos los procesadores disponibles como su nivel de paralelismo de destino.
Con la adición de esta API, Executors proporciona diferentes tipos de opciones ExecutorService.
Dependiendo de sus requisitos, puede elegir uno de ellos o puede buscar ThreadPoolExecutor que proporciona un mejor control sobre el tamaño de la cola de tareas limitadas, RejectedExecutionHandler
mecanismos.
-
static ExecutorService newFixedThreadPool(int nThreads)
Crea un grupo de subprocesos que reutiliza un número fijo de subprocesos que operan desde una cola compartida ilimitada.
-
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
Crea un grupo de subprocesos que puede programar comandos para que se ejecuten después de un retraso determinado o para que se ejecuten periódicamente.
-
static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)
Crea un grupo de subprocesos que crea nuevos subprocesos según sea necesario, pero reutilizará los subprocesos construidos previamente cuando estén disponibles, y utiliza el ThreadFactory proporcionado para crear nuevos subprocesos cuando sea necesario.
-
static ExecutorService newWorkStealingPool(int parallelism)
Crea un grupo de subprocesos que mantiene suficientes subprocesos para admitir el nivel de paralelismo dado y puede utilizar varias colas para reducir la contención.
Cada una de estas API está diseñada para satisfacer las necesidades comerciales respectivas de su aplicación. Cuál usar dependerá de los requisitos de su caso de uso.
p.ej
-
Si desea procesar todas las tareas enviadas en orden de llegada, solo use
newFixedThreadPool(1)
-
Si desea optimizar el rendimiento de un gran cálculo de tareas recursivas, utilice
ForkJoinPool
onewWorkStealingPool
-
Si desea ejecutar algunas tareas periódicamente o en un momento determinado en el futuro, utilice
newScheduledThreadPool
Echa un vistazo a otro buen artículo de PeterLawrey
sobre ExecutorService
casos de uso.
Pregunta SE relacionada:
java Fork / Join pool, ExecutorService y CountDownLatch