2011-12-23 21 views
9

En caso de que ocurra un tiempo de espera específico, debo eliminar/cancelar/interrumpir/fallar un hilo en ejecución. Utilizo ExecutorService para administrar un grupo de subprocesos, a través del cual puedo cancelar la tarea usando el método cancel() de Future que elimina esto de la vista de ExecutorService, pero el subproceso en sí continúa ejecutándose.Interrumpir/matar a un hilo en ejecución

Mirando en línea, las personas talk about interrupting threads que tienen un bucle usando el método isInterrupted() o están esperando en IO, que pueden manejarse saliendo a la superficie InterruptedException.

¿Cuál es la práctica general sobre matar hilos que no tienen bucles (o tienen otros ganchos) y no están esperando en IO? Al mirar a mi alrededor, Thread.stop() parece hacer lo que necesito (simplemente matar ciegamente el hilo) pero no se recomienda su uso.

+1

"matar a ciegas el hilo" es algo que no debes hacer, nunca. – Viruzzo

+0

Thread.stop() solo está bien para fragmentos de código triviales donde se puede entender la consecuencia de detenerse en cada línea posible. Este tipo de código también es simple de agregar líneas para verificar el indicador interrumpido. es decir, no es una solución ideal ni siquiera en teoría. –

Respuesta

3

Si utiliza un ExecutorService, entonces no debe meterse con sus hilos: esta noción está oculta detrás del ejecutor que es una noción de nivel superior a los hilos y por lo tanto no proporciona métodos para gestionarlos. Le recomiendo encarecidamente que detenga a todo el Ejecutor y no intente detener uno de sus hilos.

Tenga en cuenta que los hilos en un ExecutorService están en bucle, su bucle incluye esperar que una tarea esté disponible en su cola de tareas.

No hay media simple en Java para detener un hilo que no es un bucle, lo que puede hacer es:

  • tiene una bandera booleana volátil que Runnable cheques de la rosca de tiempo para ver si se debe parar (la misma bandera que podría usarse como condición en un bucle de hilo).
  • llamada Thread.interrupt() a tratar (mejor esfuerzo, bastante peligroso si usted no sabe lo que está haciendo) deja una espera/bloqueo/aquire relacionada con la sincronización,/... el hilo se ha quedado atascado en.
1

I personalmente te recomendaría ir por la ruta de interrupción, ya que es la forma más limpia y la forma elegante de terminar ese hilo.

Tratemos de definir bien nuestro objetivo. Un hilo no es más que un proceso separado que va a hacer un conjunto de tareas que usted le asigna que haga. Probablemente tendrá que encontrar los puntos interrumpibles en su código y tiene que hacer una verificación interrumpida() en estos puntos. Obviamente, estos puntos deberían haber llegado a una conclusión lógica.

Por ejemplo,

public void run(){ 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicA start 
     //LogicA end 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicB start 
     //LogicB end 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicLong start 
     //Long code here cannot end or exit or kill the thread now. Let it finish 
     //LogicLong ends 
     if (Thread.currentThread().interrupted()) { 
      return; 
     } 
     //LogicD start 
     //LogicD end 
} 
+0

Use Thread.interrupted() con precaución: restablece el estado de interrupción del hilo y muchas clases en el API de Java lo usan, lo que provoca que la interrupción pase desapercibida en el nivel de Thread. – Guillaume

+0

No del todo. Dando más contexto aquí, el hilo instancia una clase a través de una interfaz y llama a métodos específicos de la clase. La implementación de los métodos está definida por los usuarios de mi sistema y espero defectos como bucles infinitos. Quiero evitar esto matando los trabajos que exceden un tiempo de espera. – nija

+0

@NiranjanJayakar: En ese caso, probablemente la verificación de interrupción se debe verificar al comienzo de ese ciclo infinito. – bragboy

1

Si Alread tienen un Executorservice A continuación, han recibido una Future ya. La única manera sana y limpia de cancelar el trabajo es por lo tanto llamando al future.cancel(boolean mayInterruptIfRunning). La configuración mayInterruptIfRunning interrumpirá las tareas si se está ejecutando actualmente y no hará nada si la tarea no se está ejecutando. Por lo tanto, solo tiene que escribir el trabajo de forma tal que respete la interrupción marcando Thread.interrupted() de vez en cuando.

Tenga en cuenta la diferencia entre un trabajo y un hilo. Usted envía un trabajo y, por lo tanto, no debe ensuciar con un hilo tratando de eludir el ExecutorService que podría no ser divertido en absoluto sobre eso. Llamando al Future.cancel(true) le da a todas las partes involucradas una señal clara de qué hacer.

+0

De acuerdo. Pero quiero un equivalente de una combinación SIGTERM/SIGKILL para el hilo. No estoy contento con tener trabajos infinitamente activos o defectuosos que pueden ser costosos para mi sistema. – nija

Cuestiones relacionadas