thread sincronizacion resueltos hilos ejemplos ejemplo detener clase java multithreading wait

sincronizacion - espere hasta que todos los hilos terminen su trabajo en java



thread java (13)

Estoy escribiendo una aplicación que tiene 5 hilos que obtienen información de la web de forma simultánea y llenan 5 campos diferentes en una clase de buffer.
Necesito validar los datos del buffer y almacenarlos en una base de datos cuando todos los hilos terminen su trabajo.
¿Cómo puedo hacer esto (recibir una alerta cuando todos los hilos terminaron su trabajo)?


Además de Thread.join() sugerido por otros, java 5 introdujo el marco ejecutor. Ahí no trabajas con objetos Thread . En cambio, envía los objetos Callable o Runnable a un ejecutor. Hay un ejecutor especial que debe ejecutar múltiples tareas y devolver sus resultados fuera de servicio. Ese es el ExecutorCompletionService :

ExecutorCompletionService executor; for (..) { executor.submit(Executors.callable(yourRunnable)); }

Luego puede llamar repetidamente a take() hasta que no haya más objetos Future<?> Para devolver, lo que significa que todos se han completado.

Otra cosa que puede ser relevante, según su escenario, es CyclicBarrier .

Un asistente de sincronización que permite que un conjunto de hilos espere unos a otros para alcanzar un punto de barrera común. Los CyclicBarriers son útiles en programas que implican un grupo de hilos de tamaño fijo que ocasionalmente deben esperar el uno al otro. La barrera se llama cíclica porque puede reutilizarse después de que se liberan los hilos de espera.


Almacene los objetos de subprocesos en una colección (como una lista o un conjunto), luego recorra la colección una vez que los subprocesos se inician y llame a join en los subprocesos.


Aunque no es relevante para el problema de OP, si está interesado en la sincronización (más precisamente, una cita) con exactamente un hilo, puede usar un Exchanger

En mi caso, tuve que pausar el hilo padre hasta que el hilo hijo hizo algo, por ejemplo, completó su inicialización. Un CountDownLatch también funciona bien.


Echa un vistazo a varias soluciones.

  1. join() API join() se ha introducido en las primeras versiones de Java. Algunas buenas alternativas están disponibles con este paquete concurrent desde el lanzamiento de JDK 1.5.

  2. ExecutorService#invokeAll()

    Ejecuta las tareas dadas, devolviendo una lista de futuros que mantienen su estado y resultados cuando todo se completa.

    Refiérase a esta pregunta SE relacionada para el ejemplo del código:

    ¿Cómo usar invokeAll () para permitir que todos los subprocesos hagan su tarea?

  3. CountDownLatch

    Un asistente de sincronización que permite que uno o más subprocesos esperen hasta que se complete un conjunto de operaciones en otros subprocesos.

    Un CountDownLatch se inicializa con un conteo dado. El bloque de métodos de espera hasta que el recuento actual llega a cero debido a las invocaciones del método countDown() , después del cual se liberan todos los subprocesos en espera y las invocaciones posteriores de espera vuelven inmediatamente. Este es un fenómeno de una sola vez: el recuento no se puede restablecer. Si necesita una versión que restablece el recuento, considere usar un CyclicBarrier .

    Consulte esta pregunta para el uso de CountDownLatch

    ¿Cómo esperar un hilo que genere su propio hilo?

  4. ForkJoinPool o newWorkStealingPool() en los Executors

  5. Itera a través de todos los objetos Future creados después de enviarlos a ExecutorService


El enfoque que tomo es usar un ExecutorService para administrar pools de hilos.

ExecutorService es = Executors.newCachedThreadPool(); for(int i=0;i<5;i++) es.execute(new Runnable() { /* your task */ }); es.shutdown(); boolean finshed = es.awaitTermination(1, TimeUnit.MINUTES); // all tasks have finished or the time has been reached.


Otra posibilidad es el objeto CountDownLatch , que es útil para situaciones simples: dado que conoce de antemano el número de hilos, lo inicializa con el recuento correspondiente y pasa la referencia del objeto a cada hilo.
Una vez completada su tarea, cada subproceso llama a CountDownLatch.countDown() que disminuye el contador interno. El hilo principal, después de iniciar todos los demás, debe hacer la llamada de bloqueo CountDownLatch.await() . Se lanzará tan pronto como el contador interno haya alcanzado 0.

Preste atención que con este objeto, también se puede lanzar una InterruptedException .


Puede usar join método join para este propósito.


Puedes join a los hilos. Los bloques de unión hasta que el hilo se completa.

for (Thread thread : threads) { thread.join(); }

Tenga en cuenta que join arroja una InterruptedException . Tendrás que decidir qué hacer si eso sucede (por ejemplo, intenta cancelar los otros hilos para evitar que se realice un trabajo innecesario).



Tú lo haces

for (Thread t : new Thread[] { th1, th2, th3, th4, th5 }) t.join()

Después de esto para el ciclo, puede estar seguro de que todos los hilos han terminado sus trabajos.


Tuve un problema similar y terminé usando Java 8 parallelStream.

requestList.parallelStream().forEach(req -> makeRequest(req));

Es súper simple y legible. Detrás de escena está usando el pool de unión de horquilla predeterminado de JVM, lo que significa que esperará a que todos los hilos terminen antes de continuar. Para mi caso, fue una solución ordenada, porque era el único parallelStream en mi aplicación. Si tiene más de un parallelStream ejecutándose simultáneamente, lea el siguiente enlace.

Más información sobre transmisiones paralelas here .


Use esto en su hilo principal: while (! Executor.isTerminated ()); Coloque esta línea de código después de iniciar todos los hilos del servicio del ejecutor. Esto solo iniciará el hilo principal después de que todos los hilos iniciados por los ejecutores hayan finalizado. Asegúrese de llamar a executor.shutdown (); antes del ciclo anterior.


prueba esto, funcionará

Thread[] threads = new Thread[10]; List<Thread> allThreads = new ArrayList<Thread>(); for(Thread thread : threads){ if(null != thread){ if(thread.isAlive()){ allThreads.add(thread); } } } while(!allThreads.isEmpty()){ Iterator<Thread> ite = allThreads.iterator(); while(ite.hasNext()){ Thread thread = ite.next(); if(!thread.isAlive()){ ite.remove(); } } }