Estoy trabajando en el diseño de una aplicación que consta de tres partes:
- un solo hilo que vigila la ocurrencia de ciertos eventos (creación de archivos, solicitudes externas, etc.)
- N subprocesos de trabajo que responden a estos eventos al procesarlos (cada trabajador procesa y consume un solo evento y el procesamiento puede tomar un tiempo variable)
- un controlador que gestiona esos subprocesos y maneja los errores (reinicio de subprocesos, registro de resultados)
Aunque esto es bastante básico y no es difícil de implementar, me pregunto cuál sería la forma "correcta" de hacerlo (en este caso concreto en Java, pero también se agradecen las respuestas de abstracción más altas). Se me ocurren dos estrategias:
Observador / Observable: El controlador observa el hilo de observación. En caso de que ocurra un evento, se notifica al controlador y puede asignar la nueva tarea a un subproceso libre de un grupo de subprocesos en caché reutilizable (o esperar y almacenar en caché las tareas en la cola FIFO si todos los subprocesos están ocupados actualmente). Los subprocesos de trabajo implementan Callable y devuelven correctamente con el resultado (o un valor booleano), o regresan con un error, en cuyo caso el controlador puede decidir qué hacer (dependiendo de la naturaleza del error que ha sucedido).
Productor / Consumidor : el hilo de observación comparte un BlockingQueue con el controlador (cola de eventos) y el controlador comparte dos con todos los trabajadores (cola de tareas y cola de resultados). En caso de un evento, el hilo de observación coloca un objeto de tarea en la cola de eventos. El controlador toma nuevas tareas de la cola de eventos, las revisa y las coloca en la cola de tareas. Cada trabajador espera nuevas tareas y las toma / consume de la cola de tareas (por orden de llegada, gestionadas por la misma cola), colocando los resultados o errores nuevamente en la cola de resultados. Finalmente, el controlador puede recuperar los resultados de la cola de resultados y tomar los pasos correspondientes en caso de errores.
Los resultados finales de ambos enfoques son similares, pero cada uno tiene ligeras diferencias:
Con Observers, el control de los hilos es directo y cada tarea se atribuye a un nuevo trabajador generado específico. La sobrecarga para la creación de subprocesos puede ser mayor, pero no mucho gracias al grupo de subprocesos en caché. Por otro lado, el patrón de Observador se reduce a un solo Observador en lugar de múltiples, que no es exactamente para lo que fue diseñado.
La estrategia de la cola parece ser más fácil de extender, por ejemplo, agregar múltiples productores en lugar de uno es sencillo y no requiere ningún cambio. La desventaja es que todos los subprocesos se ejecutarían indefinidamente, incluso cuando no se realiza ningún trabajo, y el manejo de errores / resultados no se ve tan elegante como en la primera solución.
¿Cuál sería el enfoque más adecuado en esta situación y por qué? Me resulta difícil encontrar respuestas a esta pregunta en línea, porque la mayoría de los ejemplos solo tratan casos claros, como actualizar muchas ventanas con un nuevo valor en el caso del Observador o procesar con múltiples consumidores y productores. Cualquier aporte es muy apreciado.
fuente