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.
ha appena aggiunto il tag 'java', poiché è comune a qualsiasi' java'. –