Tengo un programa java que escucha en un puerto para la entrada. Basado en Input, llama a un servicio web y luego devuelve un éxito / falla al programa cliente.
Bifurco un hilo para cada conexión de cliente. La respuesta al cliente que se conecta al programa debe ser rápida.
Estas son las opciones que estoy considerando
- usar hilos regulares
- utilizar
ExecutorService
connewFixedThreadPool
- utilizar
ExecutorService
connewCachedThreadPool
La razón por la que estoy considerando grupos es porque mis hilos son de corta duración: simplemente llaman a un servicio web, devuelven el resultado al cliente y cierran la conexión.
No creo newFixedThreadPool
que sea lo correcto porque las conexiones estarían esperando en las colas para obtener un hilo.
newCachedThreadPool
hubiera sido perfecto, excepto por una cosa: los hilos mueren después de un minuto. En mi caso, recibo ráfagas de conexiones, es decir, conexiones múltiples y luego puede haber una pausa durante unos minutos y luego nuevamente ráfagas. Creo que los hilos en CachedThreadPool morirían y tendrían que volver a crearse, por lo que en este caso, a veces puede funcionar como # 1.
Idealmente, me hubiera encantado tener newCachedThreadPool
un mínimo, es decir, una configuración que dice que el número de subprocesos nunca iría por debajo de 20, por lo que los subprocesos inactivos se eliminan pero nunca se permite que pasen por debajo de un umbral mínimo.
¿Hay algo como esto disponible? ¿O hay mejores alternativas?
fuente
Respuestas:
Los métodos en la clase Executors son solo métodos convenientes para casos de uso comunes. Hay muchas más opciones disponibles para crear grupos de subprocesos.
Para crear lo mismo que Executors.newCachedThreadPool () pero con un mínimo de 20 subprocesos (esto se copia del método en Executors, con el tamaño del subproceso central cambiado de 0 a 20).
fuente
Interesante pregunta.
Yo recomendaría en contra
newCachedThreadPool
. Generará tantos hilos como sea necesario sin ningún límite superior. ¡Es malo!El enfoque sugerido por Michael parece bueno. Use
ThreadPoolExecutor
y use un número con el que se sienta cómodo como el tamaño del grupo principal. Establezca el número máximo de subprocesos en algo que desea tolerar (o su servidor puede manejar).Tenga en cuenta que no hay prácticamente nada que pueda hacer una vez que agote los recursos (la cola está llena y el número máximo de subprocesos está funcionando). En ese caso, puede hacer una de las dos cosas: dejar nuevas conexiones o aplicar contrapresión (no acepte nuevos trabajos bloqueando). TPE por defecto arroja
RejectedExecutionException
cuando está lleno, pero es fácil de implementar el comportamiento de bloqueo. De hecho, aquí hay una implementación de código abierto de BlockingThreadPoolExecutor .fuente
En cuanto a la RejectedExecutionException:
En lugar de un BlockingThreadPoolExecutor, simplemente podemos configurar el RejectedExecutionHandler en el ThreadPoolExecutor para usar el controlador CallerRunPolicy .
fuente
Creo que usar un contenedor sobre un ThreadPoolExecutor es una buena manera de hacerlo. Un contenedor para que pueda exponer algo de inicialización (como un nombre de grupo, número de subprocesos, etc.) y un método para agregar una tarea (Ejecutable) a un grupo realizado anteriormente con uno de sus métodos de inicio.
El contenedor puede cambiar qué grupo usa sin afectar otro código, además puede exponer otros métodos como el número de subprocesos, auditorías (antes / después de la tarea) de manera consistente
También puede implementar su propia fábrica de subprocesos para su grupo, que puede tener un nombre personalizado, prioridad y, como mínimo, conectar un UncaughtExceptionHandler para que pueda registrar cualquier error.
en mi envoltorio de piscina tenemos métodos como
fuente