2012-11-24 13 views
8

io sono sempre IllegalThreadStateException eccezione quando si utilizza il codice seguente: Ho già iniziato questa discussione una volta (utilizzando thread.start()) e di nuovo cercando di avviarlo in un altro luogo, in modo da utilizzare secondo il codice:arresto filo e ancora iniziare a dare IllegalThreadStateException in mora

thread.interrupt(); 
thread.start(); 

Ma thread.start() sta gettando IllegalThreadStateException.

Cosa dovrei usare per risolverlo?

+1

ha appena aggiunto il tag 'java', poiché è comune a qualsiasi' java'. –

risposta

16

Thread oggetti devono essere avviati solo una volta. Se avete bisogno di fermare/interrompere una Thread, e poi si desidera iniziare di nuovo, è necessario creare una nuova istanza, e chiamare start() su di esso:

thread.interrupt(); // if you need to make sure thread's run() method stops ASAP 
thread = new MyThreadSubclass(); 
thread.start(); 

From the API docs

IllegalThreadStateException - se il thread era già stato avviato.

so che è chiaro non è al 100% che non si può chiamare start() di nuovo, anche se in precedenza chiamato interrupt(), ma questo è il modo in cui funziona.

Se si guarda allo API docs for standard Java, questo problema è più chiaro.

+0

Grazie Nate. Ma quando stavo cercando di usare 'thread.interrupt();' Ancora una volta sta mostrando un'eccezione come - ** IllegalThreadStateException **. – AnkitRox

+0

@AnkitRox, i documenti API non mostrano che 'interrupt()' genera eccezioni. Tuttavia, suppongo che tu stia chiamando 'interrupt()' anche prima della prima volta che esegui questo codice. Avresti davvero bisogno di interrompere il thread solo se è stato avviato una volta. Quindi, le volte 2, 3, ecc. Che volete chiamare 'start()', potreste chiamare 'interrupt()' in anticipo. Potresti testare 'thread.isAlive()' prima di chiamare 'thread.interrupt()'. Se ciò non funziona, devi mostrare altro codice (ad es. Come si crea l'oggetto Thread). – Nate

+0

Ho una classe come 'AsyncUploadQuestionsAndLeads' che è estesa da' Thread'. inizializzazione oggetto Thread utilizzando: 'AsyncUploadQuestionsAndLeads uploadThread = new AsyncUploadQuestionsAndLeads (evento);' e l'avvio del filo da qualche altra parte: 'uploadThread.start();' Dopo qualche tempo, io sono utilizzando il codice come: 'uploadThread.interrupt(); uploadThread.start(); ' Questa è la mia procedura di codice che ho seguito. Un'altra domanda è: il thread si arresta automaticamente quando termina il blocco di esecuzione? – AnkitRox

7

In aggiunta alla risposta di Nate.

stati AnkitRox nel suo commento:

Grazie Nate. Stavo anche provando il tuo metodo. Ma il problema si è verificato in quel momento, è stato avviato un nuovo thread per la nuova istanza e funzionava anche il thread precedente.

Quindi sembra che il problema è "il thread è ancora in esecuzione, anche se ho chiamato interrupt su di esso". Considerate questo campione (è brutto, ma sufficiente a dimostrare l'idea principale):

final Thread t = new Thread(new Runnable() { 
    public void run() { 
     while (true) { 
      for (int i = 0; i < 100000000; i++); // simulate some action 
      System.out.println("hi, interrupted = " 
        + Thread.currentThread().isInterrupted()); 
     } 
    } 
}); 
t.start(); 
new Timer(true).schedule(
    new TimerTask() { 
     public void run() { 
      t.interrupt(); 
     } 
    }, 
    1000 // 1 second delay 
); 

nota, il filo continua a funzionare anche dopo interrupt() è stato chiamato. L'output prodotto è:

hi, interrupted = false 
hi, interrupted = true 
hi, interrupted = true 
hi, interrupted = true 
... 
hi, interrupted = true 

realtà il programma non cessa salvo chiusura con forza. Allora, cosa fa il interrupt()? Imposta semplicemente la bandiera interrotta a true. Dopo interrupt() è stato chiamato il Thread.currentThread().isInterrupted() inizia a restituire false. E questo è tutto.

altro caso è se interrupt() viene chiamato mentre il filo è bloccato in una chiamata di uno dei metodi che passi InterruptedException, allora tale metodo restituirà gettando il InterruptedException.E se il codice del thread solo "mangia" tale eccezione, allora il filo continuerà ancora in esecuzione, prendere in considerazione un campione:

final Thread t = new Thread(new Runnable() { 
    public void run() { 
     while (true) { 
      System.out.println("hi, interrupted = " 
        + Thread.currentThread().isInterrupted()); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) { 
       System.out.println("got InterruptedException"); 
      } 
     } 
    } 
}); 
t.start(); 
new Timer(true).schedule(
    new TimerTask() { 
     public void run() { 
      t.interrupt(); 
     } 
    }, 
    1000 // 1 second delay 
); 

nota, il filo continua a funzionare anche dopo interrupt() è stato chiamato. L'output prodotto è:

hi, interrupted = false 
got InterruptedException 
hi, interrupted = false 
hi, interrupted = false 
... 
hi, interrupted = false 

nota, questa volta interrupted = false anche dopo interrupt() è stato chiamato. Questo perché ogni volta che viene rilevato InterruptedException, il flag interrotto viene reimpostato su false.

In Java, l'arresto di un thread è il meccanismo cooperativo. Significa che non può essere fatto senza cooperazione dal thread stesso. Ecco la versione fissa del campione di cui sopra:

final Thread t = new Thread(new Runnable() { 
    public void run() { 
     while (!Thread.currentThread().isInterrupted()) { 
      System.out.println("hi, interrupted = " 
        + Thread.currentThread().isInterrupted()); 
      try { 
       Thread.sleep(5000); 
      } catch (InterruptedException e) { 
       System.out.println("we've been interrupted"); 
       // restore the interrupted flag 
       Thread.currentThread().interrupt(); 
      } 
     } 
    } 
}); 
t.start(); 
new Timer(true).schedule(
    new TimerTask() { 
     public void run() { 
      t.interrupt(); 
     } 
    }, 
    1000 // 1 second delay 
); 

Quindi l'approccio corretto dovrebbe essere quello di controllare periodicamente la bandiera interrotto. E se viene rilevato lo stato interrotto, è sufficiente tornare al più presto. Un'altra opzione comune non è l'uso di Thread.interrupt(), ma some custom boolean instead.

+0

ottima spiegazione. non è affatto brutto :) – Nate