2011-08-22 16 views
5

Intentando interrumpir un hilo en ejecución, en este ejemplo, t1, que se ejecuta mediante un hilo en un grupo de subprocesos.Interrumpir un hilo que duerme

t2 es el que envía la interrupción.

No puedo detener la ejecución de t1, t1 no recibe InterruptedException.

¿Qué me estoy perdiendo?

Executor exec1 = Executors.newFixedThreadPool(1); 

    // task to be interrupted 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       System.out.println("starting uninterruptible task 1"); 
       Thread.sleep(4000); 
       System.out.println("stopping uninterruptible task 1"); 
      } catch (InterruptedException e) { 
       assertFalse("This line should never be reached.", true); 
       e.printStackTrace(); 
      }    
     }   
    }; 
    final Thread t1 = new Thread(runnable); 


    // task to send interrupt 
    Runnable runnable2 = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       Thread.sleep(1000); 
       t1.interrupt(); 
       System.out.println("task 2 - Trying to stop task 1"); 
       Thread.sleep(5000); 

      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      }    
     }   
    }; 
    Thread t2 = new Thread(runnable2); 

    exec1.execute(t1); 
      t2.start(); 
    t2.join(); 

Respuesta

3

Parece que malinterpretas los hilos y los ejecutores. Se crean dos hilos de objeto para dos ejecutables, pero solo se inicia uno de ellos (t2), t1 se pasa al Ejecutor para que se ejecute dentro de él. Pero el ejecutor no necesita que se suministre el hilo, solo necesita la implementación de Runnable. El ejecutor en sí mismo es un grupo de subprocesos (por lo general, pero no es obligatorio), y solo crea (y agrupa) subprocesos dentro de él. Te ve enrutar igual de simple Runnable (que es Thread implementa). Entonces, realmente envías interrupción al hilo que nunca se inició.

Si realmente desea que su código funcione, debe eliminar Executor y simplemente iniciar ambos hilos explícitamente.

+0

Gracias BegemoT. Esto tiene sentido. – portoalet

+0

begemot tiene razón –

0

Para interrumpir el hilo ejecutor,

final ExecutorService exec1 = Executors.newFixedThreadPool(1); 
final Future<?> f = exec1.submit(runnable); 
... 
f.cancel(true); 
+0

El problema con esto es que el 'Runnable' ahora se ejecutará dos veces: una a través del grupo de hilos, y una a través del hilo' t1'. –

+0

estoy usando el ejecutor para ejecutar el hilo. – portoalet

+0

'final Futuro f = exec1.submit (ejecutable); f.cancel (verdadero);' –

0

Calling Thread.interrupt no necesariamente se producirá una InterruptedException. Puede simplemente configurar el estado interrumpido del hilo, que puede sondearse mediante Thread.interrupted() o Thread.isinterrupted.

Ver http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt() para más detalles.

+0

Se equivocó, lea la documentación con cuidado ... el método intterupt causa una excepción interrumpida, si el hilo interrumpido está durmiendo .. –

+0

.. .si el hilo interrumpido está durmiendo ... Eso es lo que quise decir, tal vez el hilo no está durmiendo cuando se interrumpe. – mort

+0

pero el hilo en la pregunta es estado dormido .. –

3

Tu error es que estás intentando ejecutar un Thread en un ThreadPool.

Esto parece a trabajar, porque Thread sucede para implementar Runnable, pero debido a que el único hilo está siendo utilizado como un Runnable y no se ha iniciado como un Thread, llamando a métodos como #interrupt() no tendrá el efecto deseado.

Si aún necesita usar un grupo de subprocesos, en su lugar debe considerar utilizar una clase como FutureTask. Envuelva su Runnable en un FutureTask, y luego envíe la tarea a un grupo de subprocesos. Luego, cuando desee interrumpir la tarea, llame al futureTask.cancel(true).

1

El problema es que nunca se puede saber realmente qué subproceso usaría el Executor para ejecutar su tarea.

Aunque haya enviado un objeto Thread, The Executor usará el subproceso creado por el grupo de subprocesos fijos. Por lo tanto, el hilo con referencia t1 no es el hilo en el que se ejecutará su tarea. así que llamar al t1.interrupt() no va a hacer nada.

Para adecuadamente manera de hacer esto es usar un ExecutorService y utilizar el submit() a presentar un objeto Runnable/Callable. Esto devolverá un Future que expone un método cancel() que se puede utilizar para cancelar la tarea.

Cuestiones relacionadas