2012-04-14 10 views
6

En mi proyecto estoy construyendo un marco de ejecución Java que recibe solicitudes de trabajo de un cliente. El trabajo (tamaño variable) se divide en un conjunto de tareas y luego se pone en cola para su procesamiento. Hay colas separadas para procesar cada tipo de tarea y cada cola está asociada a un ThreadPool. Los ThreadPools están configurados de forma tal que el rendimiento general del motor es óptimo.Trabajo/Tarea Robo ThreadPoolExecutor

Este diseño nos ayuda a balancear las solicitudes de manera efectiva y las grandes solicitudes no terminan acaparando los recursos del sistema. Sin embargo, a veces la solución se vuelve ineficaz cuando algunas de las colas están vacías y sus respectivos grupos de subprocesos permanecen inactivos.

Para hacerlo mejor, estaba pensando en implementar una técnica de robo de trabajo/tarea para que la cola con mucha carga pueda obtener ayuda de los otros ThreadPools. Sin embargo, esto puede requerir la implementación de mi propio ejecutor, ya que Java no permite asociar múltiples colas con un ThreadPool y no admite el concepto de robo de trabajo.

Lea acerca de Fork/Join, pero eso no parece ajustarse a mis necesidades. Cualquier sugerencia o forma alternativa de construir esta solución podría ser muy útil.

Gracias Andy

+1

Debería pensar en cómo mantener todas sus CPU ocupadas. No importa si alguno de sus subprocesos está inactivo si está haciendo el mejor uso posible de sus CPU. –

+0

Si los grupos de subprocesos tienen tantos subprocesos como usted tiene cpus, cualquier grupo de subprocesos individual puede "robar" toda la copia incluso si todos los demás grupos de subprocesos están inactivos. –

+0

@PeterLawrey: eso es cierto, pero si hay muchas agrupaciones, puede tener un rendimiento bajo si todos los subprocesos de todas las agrupaciones funcionan al mismo tiempo. – jtahlborn

Respuesta

1

se podría implementar una aplicación personalizada BlockingQueue (creo que es necesario sobre todo para poner en práctica los métodos offer() y take()) que está respaldado por una cola "primaria" y 0 o más colas secundarias. take siempre tomaría de la cola de respaldo principal si no está vacía, de lo contrario, puede extraer de las colas secundarias.

de hecho, puede ser mejor tener 1 grupo donde todos los trabajadores tengan acceso a todas las colas, pero "prefieran" una cola específica. puede obtener su proporción de trabajo óptima asignando diferentes prioridades a diferentes trabajadores. en un sistema completamente cargado, sus trabajadores deberían estar trabajando en la proporción óptima. en un sistema subcargado, sus trabajadores deberían poder ayudar con otras colas.

+0

Esto parece ser una buena idea que estoy intentando probar con un POC. –

2

¿Has considerado el ForkJoinPool? El marco fork-join se implementó de una forma agradable y modular para que pueda usar el grupo de subprocesos de robo de trabajo.

+1

Lee la API pero todavía no puedes entender cómo es diferente al ThreadPoolExecutor regular. Tal vez falta algunos aspectos más finos allí. –

+0

Sí, veo, lo que tiene es, de hecho, un esquema de particionado que ahora quiere flexibilizar: deje que los límites de partición cambien de acuerdo con la carga de trabajo. El "robo de trabajo" puede ser un término más especializado para los esquemas que involucran la granulación de tareas precisas: una tarea que se ejecuta en un subproceso genera subtareas y las empuja a su propio deque para que otros subprocesos puedan robar su trabajo. Entonces, si investigas con el término "particionamiento de grupos de hilos", encontrarás algo adecuado para tu caso. –

2

Java 8 tiene métodos de fábrica y de utilidad para eso en la clase Executors. Existe una implementación de un grupo de subprocesos de robo de trabajo (here) que, creo, es exactamente lo que desea.

+0

La única desventaja que veo con esto es que crea nuevas ForkJoinThreads bajo demanda en lugar de tomar prestados estos subprocesos de un grupo global; puede ser un grupo común o un grupo que el cliente puede aprobar. –

Cuestiones relacionadas