Come fermare un thread java con garbo?

Ho scritto un thread, ci vuole troppo tempo per essere eseguito e sembra che non sia stato fatto completamente. Voglio fermare il filo con grazia. Qualsiasi aiuto ?

Il modo migliore per farlo è di avere il run() del Thread protetto da una variabile boolean e impostarlo su true dall’esterno quando si vuole fermarlo, qualcosa del tipo:

 class MyThread extends Thread { volatile boolean finished = false; public void stopMe() { finished = true; } public void run() { while (!finished) { //do dirty work } } } 

C’era una volta un metodo stop() esisteva ma come afferma la documentazione

Questo metodo è intrinsecamente pericoloso. L’interruzione di una discussione con Thread.stop lo fa sbloccare tutti i monitor che ha bloccato (come conseguenza naturale dell’eccezione ThreadDeath non verificata che si propaga nello stack). Se uno qualsiasi degli oggetti precedentemente protetti da questi monitor si trovavano in uno stato incoerente, gli oggetti danneggiati diventano visibili ad altri thread, determinando potenzialmente un comportamento arbitrario.

Ecco perché dovresti avere una guardia …

La parte ctriggers sull’utilizzo di un flag per interrompere il thread è che se il thread è in attesa o in attesa, è necessario attendere che finisca l’attesa / sospensione. Se si chiama il metodo di interrupt sul thread, questo causerà l’interruzione della chiamata di attesa o sospensione con un InterruptedException.

(Una seconda parte negativa dell’approccio flag è che la maggior parte del codice non banale sta utilizzando librerie come java.util.concurrent, dove le classi sono progettate specificamente per utilizzare l’interruzione per annullare. Provare a usare il flag rollato a mano in un’attività passata in un Executir sarà imbarazzante.)

Calling interrupt () imposta anche una proprietà interrotta che è ansible utilizzare come flag per controllare se chiudere (nel caso in cui il thread non sia in attesa o in attesa).

È ansible scrivere il metodo di esecuzione del thread in modo che l’InterruptedException venga catturato al di fuori di qualsiasi logica di loop del thread, oppure è ansible rilevare l’eccezione all’interno del loop e chiudere la chiamata che genera l’eccezione, impostando il flag di interrupt all’interno del blocco catch per InterruptedException in modo che il thread non perda traccia del fatto che è stato interrotto. Il thread interrotto può ancora mantenere il controllo e terminare l’elaborazione alle sue condizioni.

Dire che voglio scrivere un thread di lavoro che funzioni in incrementi, dove c’è un sonno nel mezzo per qualche motivo, e non voglio uscire dal sonno per far sì che l’elaborazione si interrompa senza fare il lavoro rimanente per quell’incremento, voglio solo per uscire se si tratta di incrementi intermedi:

 class MyThread extends Thread { public void run() { while (!Thread.currentThread().isInterrupted()) { doFirstPartOfIncrement(); try { Thread.sleep(10000L); } catch (InterruptedException e) { // restore interrupt flag Thread.currentThread().interrupt(); } doSecondPartOfIncrement(); } } } 

Ecco una risposta a una domanda simile, incluso il codice di esempio.

Non dovresti uccidere Thread da un altro. È considerato un’abitudine abbastanza brutta. Tuttavia, ci sono molti modi. È ansible utilizzare l’istruzione return dal metodo run di thread. O puoi controllare se il thread è già stato interrotto e poi cancellerà il suo lavoro. Fe:

 while (!isInterrupted()) { // doStuff } 

Fai una stop booleana volatile da qualche parte. Quindi nel codice che viene eseguito nella discussione, regolarmente

  if (stop) // end gracefully by breaking out of loop or whatever 

Per interrompere il thread, imposta stop su true .

Penso che devi farlo manualmente in questo modo. Dopotutto, solo il codice in esecuzione nel thread ha qualche idea di cosa sia e non sia grazioso.

È necessario inviare un messaggio di arresto al thread e il thread stesso deve intervenire se il messaggio è stato ricevuto. Questo è abbastanza semplice, se l’azione di lunga durata è all’interno del loop:

 public class StoppableThread extends Thread { private volatile boolean stop = false; public void stopGracefully() { stop = true; } public void run() { boolean finished = false; while (!stop && !finished) { // long running action - finished will be true once work is done } } } 

Perché un thread si fermi, nessuno sembra aver menzionato (errare) usando l’eccezione:

 abstract class SelfStoppingThread extends Thread { @Override public final void run() { try { doRun(); } catch (final Stop stop) { //optional logging } } abstract void doRun(); protected final void stopSelf() { throw new Stop(); } private static final class Stop extends RuntimeException {}; } 

Una sottoclass ha solo bisogno di scavalcare doRun () normalmente come faresti con un Thread, e chiamare stopSelf () ogni volta che si sente come se volesse fermarsi. IMO sembra più pulito che usare un flag in un ciclo while.