Tengo un objeto con un método llamado StartDownload()
, que inicia tres hilos.
¿Cómo obtengo una notificación cuando cada hilo ha terminado de ejecutarse?
¿Hay alguna manera de saber si uno (o todos) del hilo está terminado o todavía se está ejecutando?
java
multithreading
Ricardo Felgueiras
fuente
fuente
Respuestas:
Hay varias formas de hacerlo:
¿Cómo implementar la Idea # 5? Bueno, una forma es crear primero una interfaz:
luego cree la siguiente clase:
y luego cada uno de sus hilos se extenderá
NotifyingThread
y en lugar de implementarlorun()
se implementarádoRun()
. Por lo tanto, cuando se completen, notificarán automáticamente a cualquiera que esté esperando la notificación.Finalmente, en su clase principal, la que inicia todos los subprocesos (o al menos el objeto que espera la notificación), modifique esa clase
implement ThreadCompleteListener
e inmediatamente después de crear cada subproceso se agrega a la lista de oyentes:luego, a medida que sale cada subproceso,
notifyOfThreadComplete
se invocará su método con la instancia de subproceso que acaba de completarse (o bloquearse).Tenga en cuenta que sería mejor que
implements Runnable
en vez deextends Thread
paraNotifyingThread
como hilo que se extiende por lo general se desaconseja en nuevo código. Pero estoy codificando tu pregunta. Si cambia laNotifyingThread
clase para implementar,Runnable
entonces tiene que cambiar parte de su código que administra los subprocesos, lo cual es bastante sencillo de hacer.fuente
notify
método, no en elrun
método, sino después.Solución usando CyclicBarrier
label0 : la barrera cíclica se crea con un número de partes igual al número de subprocesos en ejecución más uno para el subproceso principal de ejecución (en el que se ejecuta startDownload ())
etiqueta 1 - n-th DownloadingThread entra en la sala de espera
etiqueta 3 : NUMBER_OF_DOWNLOADING_THREADS han entrado en la sala de espera. El hilo principal de ejecución los libera para comenzar a realizar sus tareas de descarga más o menos al mismo tiempo
etiqueta 4 : el hilo principal de ejecución ingresa a la sala de espera. Esta es la parte 'más complicada' del código para entender. No importa qué hilo ingresará a la sala de espera por segunda vez. Es importante que cualquier subproceso que entre en la sala al final garantice que todos los otros subprocesos de descarga hayan finalizado sus trabajos de descarga.
etiqueta 2 - n-th DownloadingThread ha terminado su trabajo de descarga y entra en la sala de espera. Si es el último, es decir, ya NUMBER_OF_DOWNLOADING_THREADS lo han ingresado, incluido el hilo principal de ejecución, el hilo principal continuará su ejecución solo cuando todos los otros hilos hayan terminado de descargarse.
fuente
Realmente debería preferir una solución que utilice
java.util.concurrent
. Encuentra y lee a Josh Bloch y / o Brian Goetz sobre el tema.Si no está utilizando
java.util.concurrent.*
y está asumiendo la responsabilidad de usar subprocesos directamente, entonces probablemente deberíajoin()
saber cuándo se realiza un subproceso. Aquí hay un mecanismo de devolución de llamada súper simple. Primero extienda laRunnable
interfaz para tener una devolución de llamada:Luego crea un Ejecutor que ejecutará tu ejecutable y te devolverá la llamada cuando termine.
El otro tipo de cosa obvia para agregar a su
CallbackRunnable
interfaz es un medio para manejar cualquier excepción, así que tal vez ponga unapublic void uncaughtException(Throwable e);
línea allí y en su ejecutor, instale un Thread.UncaughtExceptionHandler para enviarlo a ese método de interfaz.Pero hacer todo lo que realmente comienza a oler
java.util.concurrent.Callable
. Realmente debería considerar el usojava.util.concurrent
si su proyecto lo permite.fuente
runner.join()
y luego cualquier código que desee después de eso, ya que sabe que el hilo ha terminado. ¿Es solo que puedes definir ese código como una propiedad de los ejecutables, para que puedas tener diferentes cosas para diferentes ejecutables?runner.join()
es la forma más directa de esperar. Asumí que el OP no quería bloquear su hilo principal de llamadas ya que pidieron ser "notificados" para cada descarga, lo que podría completarse en cualquier orden. Esto ofreció una forma de recibir notificaciones de forma asincrónica.¿Quieres esperar a que terminen? Si es así, use el método Join.
También existe la propiedad isAlive si solo desea verificarla.
fuente
Thread
tostart
, que hace el hilo, pero la llamada vuelve inmediatamente.isAlive
debería ser una simple prueba de bandera, pero cuando busqué en Google el método fuenative
.Puede interrogar la instancia de subproceso con getState () que devuelve una instancia de enumeración Thread.State con uno de los siguientes valores:
Sin embargo, creo que sería un mejor diseño tener un hilo maestro que espere a que los 3 hijos terminen, el maestro continuará la ejecución cuando los otros 3 hayan terminado.
fuente
También podría usar el
Executors
objeto para crear un grupo de subprocesos ExecutorService . Luego use elinvokeAll
método para ejecutar cada uno de sus hilos y recuperar futuros. Esto se bloqueará hasta que todos hayan terminado la ejecución. Su otra opción sería ejecutar cada uno usando el grupo y luego llamarawaitTermination
para bloquear hasta que el grupo termine de ejecutarse. Solo asegúrese de llamarshutdown
() cuando termine de agregar tareas.fuente
Muchas cosas han cambiado en los últimos 6 años en el frente de subprocesos múltiples.
En lugar de usar
join()
y bloquear la API, puede usar1. API de ExecutorService
invokeAll()
2. CountDownLatch
3. ForkJoinPool o
newWorkStealingPool()
en Executors es otra forma4.Interate a través de todas las
Future
tareas desde el envíoExecutorService
y verifica el estado bloqueando la llamadaget()
en elFuture
objetoEche un vistazo a las preguntas SE relacionadas:
¿Cómo esperar un hilo que genera su propio hilo?
Ejecutores: ¿Cómo esperar sincrónicamente hasta que todas las tareas hayan terminado si las tareas se crean de forma recursiva?
fuente
Sugeriría mirar el javadoc para la clase Thread .
Tienes múltiples mecanismos para la manipulación de hilos.
Su hilo principal podría ser
join()
los tres hilos en serie, y luego no continuaría hasta que los tres hayan terminado.Encuesta el estado del hilo de los hilos generados a intervalos.
Coloca todos los hilos generados en un separado
ThreadGroup
y sondeaactiveCount()
en elThreadGroup
y espera a que llegue a 0.Configure una devolución de llamada personalizada o un tipo de interfaz de escucha para la comunicación entre subprocesos.
Estoy seguro de que todavía me faltan muchas otras formas.
fuente
Aquí hay una solución simple, corta, fácil de entender y que funciona perfectamente para mí. Necesitaba dibujar en la pantalla cuando otro hilo termina; pero no pudo porque el hilo principal tiene el control de la pantalla. Entonces:
(1) Creé la variable global:
boolean end1 = false;
el hilo lo establece en verdadero cuando finaliza. Eso es recogido en el hilo principal por el bucle "postDelayed", donde se responde.(2) Mi hilo contiene:
(3) Afortunadamente, "postDelayed" se ejecuta en el hilo principal, por lo que es allí donde se verifica el otro hilo una vez por segundo. Cuando termina el otro hilo, esto puede comenzar lo que queramos hacer a continuación.
(4) Finalmente, comience a ejecutar todo en algún lugar de su código llamando a:
fuente
Supongo que la forma más fácil es usar la
ThreadPoolExecutor
clase.que es exactamente lo que necesitamos Anularemos
afterExecute()
para obtener devoluciones de llamada después de que se realice cada subproceso y anularemosterminated()
para saber cuándo se realizan todos los subprocesos.Entonces esto es lo que debes hacer
Crear un ejecutor:
Y comienza tus hilos:
Dentro del método,
informUiThatWeAreDone();
haga lo que necesite hacer cuando todos los hilos estén terminados, por ejemplo, actualice la IU.NOTA: No se olvide de usar
synchronized
métodos, ya que hace su trabajo en paralelo y TENGA MUY PRECAUCIÓN si decide llamar alsynchronized
método desde otrosynchronized
método! Esto a menudo conduce a puntos muertos¡Espero que esto ayude!
fuente
También puede usar SwingWorker, que tiene soporte de cambio de propiedad incorporado. Consulte addPropertyChangeListener () o el método get () para ver un ejemplo de escucha de cambio de estado.
fuente
Mire la documentación de Java para la clase Thread. Puede verificar el estado del hilo. Si coloca los tres hilos en las variables miembro, los tres hilos pueden leer los estados de cada uno.
Sin embargo, debes tener un poco de cuidado, ya que puedes causar condiciones de carrera entre los hilos. Solo trate de evitar una lógica complicada basada en el estado de los otros hilos. Definitivamente evite que varios hilos escriban en las mismas variables.
fuente