2011-08-22 19 views
5

Tentativo di interrompere un thread in esecuzione, in questo esempio, t1, che viene eseguito da un thread in un pool di thread.Interruzione di un thread in sospensione

t2 è quello che invia l'interrupt.

Impossibile interrompere l'esecuzione t1, t1 non ottiene InterruptedException.

Cosa mi manca?

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(); 

risposta

3

Sembra che tu abbia frainteso discussioni ed Esecutori. Crei due oggetti thread per due runnables, ma ne inizi solo uno (t2), t1 passi a Executor per eseguirlo al suo interno. Ma l'esecutore non ha bisogno di Thread per essere fornito - ha solo bisogno di implementazione Runnable. L'Executor stesso è un pool di thread (in genere, ma non è obbligatorio) e crea solo thread (e pool) al suo interno. Ti vede thread esattamente come Runnable (che è Thread implementa). Quindi invii effettivamente interrupt al thread che non è mai stato avviato.

Se si desidera veramente che il codice funzioni, è necessario rimuovere Executor e avviare entrambi i thread in modo esplicito.

+0

Grazie BegemoT. Questo ha senso. – portoalet

+0

begemot ha ragione –

0

Per interrompere il filo esecutore,

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

Il problema con questo è che il 'Runnable' verrà eseguito due volte: una volta tramite il pool di thread e una volta tramite il thread' t1'. –

+0

sto usando l'executor per eseguire il thread. – portoalet

+0

'finale Future f = exec1.submit (eseguibile); f.cancel (true);' –

0

Calling Thread.interrupt non necessariamente genera un InterruptedException. Può semplicemente impostare lo stato interrotto del thread, che può essere interrogato da Thread.interrupted() o Thread.isInterrupted.

Vedere http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt() per ulteriori dettagli.

+0

Hai sbagliato, leggere attentamente la documentazione .. metodo intterupt provoca eccezione interrotta, se il filo interrotto sta dormendo .. –

+0

.. .se il thread interrotto sta dormendo ... Questo è quello che intendevo, forse il thread non sta dormendo quando viene interrotto. – mort

+0

ma il thread alla domanda è in stato di sospensione .. –

3

L'errore è che si sta tentando di eseguire un Thread su un ThreadPool.

Questo appare lavorare, perché Thread accade per attuare Runnable, ma perché il filo è utilizzato solo come Runnable e non viene avviato come Thread, chiamando metodi come #interrupt() non avrà l'effetto desiderato.

Se è ancora necessario utilizzare un pool di thread, è consigliabile utilizzare una classe come FutureTask. Avvolgere il tuo in un FutureTask e quindi inviare l'attività a un pool di thread. Quindi, quando si desidera interrompere l'attività, chiamare futureTask.cancel(true).

1

Il problema è che non è mai possibile sapere quale thread verrà utilizzato da Executor per eseguire l'attività.

Anche se è stato inviato un oggetto Thread, Executor utilizzerà il thread creato dal pool di thread fisso. Pertanto il thread con riferimento t1 non è il thread in cui verrà eseguita l'attività. quindi chiamare t1.interrupt() non farà nulla.

Per corretto modo per farlo è quello di utilizzare un ExecutorService e utilizzare il submit() di presentare un oggetto Runnable/Callable. Ciò restituirà un Future che espone un metodo cancel() che può essere utilizzato per annullare l'attività.

Problemi correlati