Odpowiedzi:
Ma to na celu utrzymanie stanu .
Kiedy złapiesz go InterruptException
i połkniesz, zasadniczo zapobiegniesz zauważeniu przerwania przez metody wyższego poziomu / grupy wątków. Co może powodować problemy.
Wywołując Thread.currentThread().interrupt()
, ustawiasz flagę przerwania wątku, aby programy obsługi przerwań wyższego poziomu zauważyły to i mogły odpowiednio obsłużyć.
Współbieżność języka Java w praktyce omówiono bardziej szczegółowo w rozdziale 7.1.3: Reagowanie na przerwanie . Jego zasada brzmi:
Tylko kod, który implementuje politykę przerywania wątku, może połknąć żądanie przerwania. Zadanie ogólnego przeznaczenia i kod biblioteki nigdy nie powinny połykać żądań przerwania.
interrupt()
połączenie jest jedynym sposobem na ustawienie flagi przerwania, gdy otrzymałeś powiadomienie o tym stanie za pośrednictwem innego „mechanizmu dostarczania” - InterruptedException
i chcesz lub nie możesz go ponownie wysłać.
Myślę, że ten przykład kodu wyjaśnia sprawę. Klasa, która wykonuje zadanie:
public class InterruptedSleepingThread extends Thread {
@Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i=0;i<Integer.MAX_VALUE;i++) {
//You are kidding me
System.out.println(i + " " + i*2);
//Let me sleep <evil grin>
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
}else {
sleepBabySleep();
}
}
}
/**
*
*/
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
Główna klasa:
public class InterruptedSleepingThreadMain {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
InterruptedSleepingThread thread = new InterruptedSleepingThread();
thread.start();
//Giving 10 seconds to finish the job.
Thread.sleep(10000);
//Let me interrupt
thread.interrupt();
}
}
Spróbuj wywołać przerwanie bez przywracania stanu.
Uwaga:
Jak zatrzymać wątek, który czeka przez długi czas (np. Na dane wejściowe)?
Aby ta technika zadziałała, ważne jest, aby każda metoda, która wyłapuje wyjątek przerwania i nie jest przygotowana do jego rozwiązania, natychmiast ponownie potwierdza wyjątek. Mówimy raczej o ponownym potwierdzeniu niż o ponownym zgłoszeniu, ponieważ nie zawsze jest możliwe ponowne zgłoszenie wyjątku. Jeśli metoda przechwytująca InterruptedException nie jest zadeklarowana do zgłaszania tego (zaznaczonego) wyjątku, powinna „przerwać się ponownie” z następującą inkantacją:
Thread.currentThread().interrupt();
Gwarantuje to, że Thread ponownie wywoła InterruptedException, gdy tylko będzie to możliwe.
Uznałbym to za złą praktykę lub przynajmniej trochę ryzykowną. Zwykle metody wyższego poziomu nie wykonują operacji blokujących i nigdy ich InterruptedException
tam nie zobaczą . Jeśli zamaskujesz to w każdym miejscu, w którym wykonujesz operację przerywaną, nigdy jej nie uzyskasz.
Jedynym uzasadnieniem dla Thread.currentThread.interrupt()
i nie zgłaszania żadnego innego wyjątku lub sygnalizowania żądania przerwania w jakikolwiek inny sposób (np. Ustawienie interrupted
zmiennej lokalnej w głównej pętli wątku) jest sytuacja, w której naprawdę nie można nic zrobić z wyjątkiem, jak w finally
blokach.
Zobacz odpowiedź Pétera Töröka, jeśli chcesz lepiej zrozumieć konsekwencje Thread.currentThread.interrupt()
rozmowy.
Zapoznaj się z dokumentacją java
Jeśli ten wątek zostanie zablokowany w wywołaniu funkcji wait (), join (), sleep (long), wówczas stan jego przerwania zostanie wyczyszczony i otrzyma wyjątek InterruptedException.
Jeśli ten wątek jest zablokowany w operacji we / wy, stan przerwania wątku zostanie ustawiony, a wątek otrzyma ClosedByInterruptException.
Jeśli ten wątek jest zablokowany w selektorze, wówczas stan przerwania wątku zostanie ustawiony i powróci on natychmiast po operacji wyboru.
Jeśli żaden z poprzednich warunków nie jest spełniony, stan przerwania tego wątku zostanie ustawiony.
Tak więc, jeśli zmienisz metodę sleepBabySleep () w @Ajay George Answer to I / O operation lub po prostu sysout, nie musisz ponownie ustawiać statusu, aby zatrzymać program. (BTW, nawet nie rzucają InterruptedException)
Tak jak powiedział @ Péter Török => Ma to na celu utrzymanie stanu. (Szczególnie w przypadku metody, która spowoduje zgłoszenie InterruptedException)
InterruptedException
kasowania statusu przerwania, kiedy to robi. Myślę, że to wyjaśnia, dlaczego należy zachować stan przerwania.