Oprócz odpowiedzi Nate'a.
stany AnkitRox w swoim komentarzu:
Dzięki Nate. Próbowałem też twojej metody. Ale pojawił się problem w tym czasie, był to początek nowego wątku dla nowej instancji i poprzedni wątek również działał.
Wygląda więc na to, że problem jest „nitka wciąż działa nawet wtedy, gdy zadzwoniłem przerwanie na nim”. Rozważmy tę próbkę (jest brzydki, ale wystarczy, aby pokazać główną ideę):
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
);
Uwaga, wątek kontynuuje działanie nawet po interrupt()
została wywołana. Wydajność produkowana to:
hi, interrupted = false
hi, interrupted = true
hi, interrupted = true
hi, interrupted = true
...
hi, interrupted = true
W rzeczywistości program nigdy się nie kończy, chyba że zostanie zamknięty. Więc co wtedy robi interrupt()
? Ustawia on po prostu flagę przerwaną na na true
. Po nazwie interrupt()
został nazwany Thread.currentThread().isInterrupted()
zaczyna zwracać false
. I to wszystko.
Innym przykładem jest sytuacja, gdy interrupt()
nazywa natomiast wątek jest zablokowany w wywołanie jednej z metod, które rzucają InterruptedException
, wówczas sposób powraca wyrzuceniem InterruptedException
.A jeśli kod wątku tylko „zjada” to wyjątek, to wątek będzie nadal działa, należy rozważyć próbkę:
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
);
Uwaga, wątek kontynuuje działanie nawet po interrupt()
została wywołana. Wytworzony wyjściowy:
hi, interrupted = false
got InterruptedException
hi, interrupted = false
hi, interrupted = false
...
hi, interrupted = false
Uwaga, tym razem interrupted = false
nawet po interrupt()
została wywołana. Dzieje się tak dlatego, że gdy zostanie przechwycone InterruptedException
, flaga przerywana zostanie zresetowana do false
.
W języku Java zatrzymywanie wątku jest mechanizmem spółdzielczym. Oznacza to, że nie można tego zrobić bez współpracy z samym wątkiem. Oto ustalona wersja powyższej próbki:
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
);
więc prawidłowe podejście powinno być okresowo sprawdzać przerwany flagę. A jeśli wykryty zostanie stan przerwania, po prostu zwróć ASAP. Inną popularną opcją nie jest używanie w ogóle Thread.interrupt()
, ale some custom boolean instead.
właśnie dodano znacznik 'java', ponieważ jest on wspólny dla każdego' java'. –