example - Esperando mĂșltiples hilos para completar en Java
graphics java example (5)
Durante el curso de la ejecución de mi programa, se inician varios hilos. La cantidad de subprocesos varía según la configuración definida por el usuario, pero todos están ejecutando el mismo método con diferentes variables.
En algunas situaciones, se requiere una limpieza a mediados de la ejecución, parte de esto es detener todos los hilos, no quiero que se detengan inmediatamente, solo establezco una variable que ellos verifican para que los termine. El problema es que puede pasar hasta 1/2 segundo antes de que el hilo se detenga. Sin embargo, necesito estar seguro de que todos los hilos se hayan detenido antes de que la limpieza continúe. La limpieza se ejecuta desde otro subproceso, así que técnicamente necesito que este subproceso espere a que los otros subprocesos terminen.
He pensado en varias formas de hacerlo, pero todas parecen ser demasiado complejas. Esperaba que hubiera algún método que pueda esperar a que se complete un grupo de hilos. ¿Existe algo como esto?
Gracias.
¿Has visto las clases de Executor
en java.util.concurrent
? Puede ejecutar sus hilos a través de un ExecutorService
. Le da un objeto único que puede usar para cancelar los hilos o esperar a que se completen.
Defina un método de utilidad (o métodos) usted mismo:
public static waitFor(Collection<? extends Thread) c) throws InterruptedException {
for(Thread t : c) t.join();
}
O puede tener una matriz
public static waitFor(Thread[] ts) throws InterruptedException {
waitFor(Arrays.asList(ts));
}
De forma alternativa, podría considerar el uso de un CyclicBarrier
en la biblioteca java.util.concurrent
para implementar un punto de encuentro arbitrario entre múltiples hilos.
Si controla la creación de los Threads (envío a un ExecutorService), entonces parece que puede usar un ExecutorCompletionService
consulte ExecutorCompletionService? ¿Por qué necesitamos uno si tenemos invokeAll? para varias respuestas allí.
Si no controla la creación de subprocesos, aquí hay un enfoque que le permite unir los subprocesos "uno por uno mientras terminan" (y saber cuál termina primero, etc.), inspirados en la clase Ruby ThreadWait . Básicamente, al renovar "mirar temas" que alertan cuando terminan los otros hilos, puede saber cuándo termina el "próximo" hilo de muchos.
Lo usarías algo como esto:
JoinThreads join = new JoinThreads(threads);
for(int i = 0; i < threads.size(); i++) {
Thread justJoined = join.joinNextThread();
System.out.println("Done with a thread, just joined=" + justJoined);
}
Y la fuente:
public static class JoinThreads {
java.util.concurrent.LinkedBlockingQueue<Thread> doneThreads =
new LinkedBlockingQueue<Thread>();
public JoinThreads(List<Thread> threads) {
for(Thread t : threads) {
final Thread joinThis = t;
new Thread(new Runnable() {
@Override
public void run() {
try {
joinThis.join();
doneThreads.add(joinThis);
}
catch (InterruptedException e) {
// "should" never get here, since we control this thread and don''t call interrupt on it
}
}
}).start();
}
}
Thread joinNextThread() throws InterruptedException {
return doneThreads.take();
}
}
Lo bueno de esto es que funciona con hilos de Java genéricos, sin modificaciones, se puede unir cualquier hilo. La advertencia es que requiere un poco de creación de hilo adicional. Además, esta implementación particular "deja hilos atrás" si no llama a joinNextThread () el número completo de veces, y no tiene un método "cerrado", etc. Comente aquí si desea crear una versión más pulida. También podría usar este mismo tipo de patrón con "Futures" en lugar de objetos Thread, etc.
Si está utilizando Java 1.5 o superior, puede probar CyclicBarrier . Puede pasar la operación de limpieza como su parámetro de constructor, y simplemente llame a barrier.await()
en todos los hilos cuando haya una necesidad de limpieza.
Solo únete a ellos uno por uno:
for (Thread thread : threads) {
thread.join();
}
(Tendrá que hacer algo con InterruptedException
, y es posible que desee proporcionar un tiempo de espera en caso de que las cosas salgan mal, pero esa es la idea básica ...)