Me he sentido frustrado durante algún tiempo con el comportamiento predeterminado ThreadPoolExecutor
que respalda los ExecutorService
grupos de subprocesos que muchos de nosotros usamos. Para citar de los Javadocs:
Si hay más subprocesos que corePoolSize pero menos que maximumPoolSize en ejecución, se creará un nuevo subproceso solo si la cola está llena .
Lo que esto significa es que si define un grupo de subprocesos con el siguiente código, nunca iniciará el segundo subproceso porque LinkedBlockingQueue
no tiene límites.
ExecutorService threadPool =
new ThreadPoolExecutor(1 /*core*/, 50 /*max*/, 60 /*timeout*/,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(/* unlimited queue */));
Solo si tiene una cola limitada y la cola está llena, se iniciarán los subprocesos por encima del número principal. Sospecho que un gran número de programadores junior de Java multiproceso desconocen este comportamiento de ThreadPoolExecutor
.
Ahora tengo un caso de uso específico donde esto no es óptimo. Estoy buscando formas, sin escribir mi propia clase de TPE, para solucionarlo.
Mis requisitos son para un servicio web que realice devoluciones de llamadas a un tercero posiblemente no confiable.
- No quiero hacer la devolución de llamada sincrónicamente con la solicitud web, así que quiero usar un grupo de subprocesos.
- Por lo general, obtengo un par de estos por minuto, por lo que no quiero tener
newFixedThreadPool(...)
una gran cantidad de subprocesos que en su mayoría están inactivos. - De vez en cuando obtengo una ráfaga de este tráfico y quiero escalar el número de subprocesos a un valor máximo (digamos 50).
- Necesito hacer un mejor intento para hacer todas las devoluciones de llamada, así que quiero poner en cola las adicionales por encima de 50. No quiero abrumar al resto de mi servidor web usando un
newCachedThreadPool()
.
¿Cómo puedo evitar esta limitación en la ThreadPoolExecutor
que la cola debe estar limitada y llena antes de que se inicien más subprocesos? ¿Cómo puedo hacer que inicie más subprocesos antes de poner en cola las tareas?
Editar:
@Flavio hace un buen punto sobre el uso de ThreadPoolExecutor.allowCoreThreadTimeOut(true)
para que los hilos principales se agoten y salgan. Lo consideré, pero todavía quería la función de hilos centrales. No quería que la cantidad de subprocesos en el grupo cayera por debajo del tamaño del núcleo si es posible.