FixedThreadPool vs CachedThreadPool: el menor de dos males


Así que tengo un programa que genera hilos (~5-150) que realizan un montón de tareas. Originalmente usé un FixedThreadPool porque esta pregunta similar sugirió que eran más adecuados para tareas de vida más larga y con mi conocimiento muy limitado de multithreading, consideré la vida promedio de los hilos (varios minutos) " long lived".

Sin embargo, recientemente agregué la capacidad de generar subprocesos adicionales y hacerlo me lleva por encima del límite de subprocesos que establecí. En este caso, sería mejor adivinar y aumentar el número de hilos que puedo permitir o cambiar a un CachedThreadPool para que no tenga hilos desperdiciados?

Probándolos a ambos preliminarmente, no parece ser una diferencia, así que me inclino a ir con el CachedThreadPool solo para evitar el desperdicio. Sin embargo, ¿la vida útil de los hilos significa que debería elegir un FixedThreadPool y simplemente tratar con los hilos no utilizados? Esta pregunta hace que parezca que esos hilos adicionales no se desperdician, pero lo haría agradezco la aclaración.

Author: Ravindra babu, 2013-07-31

3 answers

Un CachedThreadPool es exactamente lo que debe usar para su situación, ya que no hay consecuencias negativas al usar uno para subprocesos largos. El comentario en el documento de Java sobre CachedThreadPools siendo adecuado para tareas cortas simplemente sugiere que son particularmente apropiados para tales casos, no que no pueden o no deben ser utilizados para tareas que involucran tareas de larga ejecución.

Para profundizar, Ejecutores.newCachedThreadPool y Ejecutores.newFixedThreadPool están respaldados por la misma implementación de thread pool (al menos en el JDK abierto) solo con diferentes parámetros. Las diferencias solo son su subproceso mínimo, máximo, tiempo de interrupción del subproceso y tipo de cola.

public static ExecutorService newFixedThreadPool(int nThreads) {
     return new ThreadPoolExecutor(nThreads, nThreads,
                                   0L, TimeUnit.MILLISECONDS,
                                   new LinkedBlockingQueue<Runnable>());
 }

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                 60L, TimeUnit.SECONDS,
                                 new SynchronousQueue<Runnable>());
}

Un FixedThreadPool tiene sus ventajas cuando de hecho desea trabajar con un número fijo de subprocesos, ya que entonces puede enviar cualquier número de tareas al servicio ejecutor sabiendo que el número de subprocesos será mantenido en el nivel que especificó. Si desea aumentar explícitamente el número de subprocesos, entonces esta no es la opción adecuada.

Sin embargo, esto significa que el único problema que puede tener con CachedThreadPool es en lo que respecta a limitar el número de subprocesos que se ejecutan simultáneamente. El CachedThreadPool no los limitará para usted, por lo que puede que necesite escribir su propio código para asegurarse de que no ejecuta demasiados hilos. Esto realmente depende del diseño de su aplicación y cómo se envían las tareas al servicio ejecutor.

 87
Author: Trevor Freeman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-17 06:11:56

Tanto FixedThreadPool como CachedThreadPool son males en aplicaciones altamente cargadas.

CachedThreadPool es más peligroso que FixedThreadPool

Si su aplicación está altamente cargada y exige baja latencia, es mejor deshacerse de ambas opciones debido a los inconvenientes siguientes

  1. Naturaleza ilimitada de la cola de tareas : Puede causar falta de memoria o alta latencia
  2. Los subprocesos largos causarán que CachedThreadPool se salgan de control al crear subprocesos

Ya que sabes que ambos son males, mal menor no hace el bien. Prefer ThreadPoolExecutor, que proporciona un control granular sobre muchos parámetros.

  1. Establezca la cola de tareas como cola acotada para tener un mejor control
  2. Have right RejectionHandler-Your own RejectionHandler or Default handlers provided by JDK
  3. Si tiene algo que hacer antes / después de completar la tarea, anule beforeExecute(Thread, Runnable) y afterExecute(Runnable, Throwable)
  4. Override ThreadFactory si se requiere personalización del hilo
  5. Control Tamaño del grupo de subprocesos dinámicamente en tiempo de ejecución (pregunta relacionada : Grupo de subprocesos dinámico)
 29
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-17 14:46:12

Así que tengo un programa que genera hilos (~5-150) que realizan un montón de tareas.

¿Está seguro de entender cómo los hilos son realmente procesados por su sistema operativo y el hardware de su elección? Cómo Java asigna subprocesos a subprocesos del sistema operativo, cómo asigna subprocesos a subprocesos de la CPU, etc.? Estoy preguntando porque crear 150 subprocesos dentro de un JRE solo tiene sentido si tiene núcleos/subprocesos de CPU masivos debajo, lo que probablemente no es el caso. Dependiendo del sistema operativo y la RAM en uso, la creación más de n hilos podrían incluso resultar en que su JRE se termine debido a errores de OOM. Por lo tanto, realmente debe distinguir entre los hilos y el trabajo que hacer por esos hilos, cuántos trabajos incluso puede procesar, etc.

Y ese es el problema con CachedThreadPool: No tiene sentido poner en cola el trabajo de larga duración en subprocesos que en realidad no pueden ejecutarse porque solo tiene 2 núcleos de CPU capaces de procesar esos subprocesos. Si terminas con 150 hilos programados, podrías crear muchos sobrecarga innecesaria para los schedulers usados dentro de Java y el sistema operativo para procesarlos simultáneamente. Esto es simplemente imposible si solo tiene 2 núcleos de CPU, a menos que sus subprocesos estén esperando E / S o algo así todo el tiempo. Pero incluso en ese caso, muchos hilos crearían una gran cantidad de E/S...

Y ese problema no ocurre con FixedThreadPool, creado con, por ejemplo, 2+n hilos, donde n es razonablemente bajo, por supuesto, porque con ese hardware y los recursos del sistema operativo se utilizan con mucha menos sobrecarga para administrar hilos que no se pueden ejecutar de todos modos.

 5
Author: Thorsten Schöning,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-10 10:31:23