"Cześć Amigo!

„Wszystko, co nowe, jest po prostu czymś starym, o czym zapomnieliśmy. Dzisiaj opowiem o zatrzymywaniu wątków. Mam nadzieję, że już zapomniałeś, jak działa metoda przerwania()”.

– Tak, Ellie, zupełnie o tym zapomniałem.

„Świetnie. W takim razie ci przypomnę”.

„W Javie, jeśli ktoś chce zatrzymać działający wątek, może zasygnalizować to temu wątkowi. Aby to zrobić, należy ustawić zmienną ukrytą isInterrupted obiektu Thread na wartość true”.

„Każdy wątek ma metodę przerwania (), która jest używana do ustawiania tej flagi. Kiedy metoda przerwania () jest wywoływana, zmienna isInterrupted wewnątrz obiektu Thread jest ustawiana na wartość true”.

„A kiedy metoda Thread.sleep() lub join() jest wywoływana w wątku, metoda sprawdza, czy flaga isInterrupted jest ustawiona dla bieżącego wątku. Jeśli ta flaga jest ustawiona (zmienna isInterrupted równa się true), wówczas metody rzucić wyjątek InterruptedException ”.

„Tutaj przypomnę ci stary przykład:”

Kod Opis
class Clock implements Runnable
{
public void run()
{
Thread current = Thread.currentThread();

while (!current.isInterrupted())
{
Thread.sleep(1000);
System.out.println("Tik");
}
}
}
Metoda run zegara pobiera obiekt Thread dla bieżącego wątku.

Klasa Clock zapisuje słowo „Tick” do konsoli raz na sekundę, o ile zmienna isInterrupt bieżącego wątku ma wartość false.

Kiedy isInterrupt staje się prawdą, metoda run zostaje zakończona.

public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clockThread.interrupt();
}
Główny wątek rozpoczyna wątek potomny (zegar), który powinien działać w nieskończoność.

Poczekaj 10 sekund i anuluj zadanie, wywołując metodę przerwania.

Główny wątek kończy swoją pracę.

Wątek zegara kończy swoją pracę.

„Tutaj używamy metody uśpienia jako części nieskończonej pętli w metodzie run . W pętli zmienna isInterrupt jest sprawdzana automatycznie. Jeśli wątek wywołuje metodę uśpienia , metoda najpierw sprawdza, czy isInterrupt jest prawdziwe dla tego wątku (tzw. taki, który wywołał metodę uśpienia). Jeśli to prawda, metoda nie będzie uśpiona. Zamiast tego zgłasza wyjątek InterruptedException ”.

„Ale w tym przykładzie stale sprawdzamy zmienną isInterrupted w stanie pętli”.

„Pamiętam, że były pewne powody, dla których nie mogliśmy zastosować tego podejścia. Czy możesz mi przypomnieć?”

Po pierwsze , metoda run nie zawsze ma pętlę. Metoda może po prostu składać się z kilkudziesięciu wywołań innych metod. W takim przypadku przed każdym wywołaniem metody trzeba by dodać sprawdzenie isInterrupted”.

Po drugie , wykonanie niektórych metod obejmujących wiele różnych działań może zająć bardzo dużo czasu”.

Po trzecie , zgłoszenie wyjątku nie zastępuje sprawdzenia isInterrupted. To tylko wygodny dodatek. Zgłoszony wyjątek pozwala szybko cofnąć stos wywołań z powrotem do samej metody run ”.

Po czwarte , metoda uśpienia jest często używana. Okazuje się, że ta pomocna metoda jest wzmocniona przez niejawną kontrolę, która jest nie mniej pomocna. To  tak, jakby nikt specjalnie nie dodał kontroli, ale tak jest.  Jest to bardzo cenne, gdy używasz cudzego kodu i nie możesz sam dodać czeku."

Po piąte , dodatkowa kontrola nie obniża wydajności. Wywołanie metody sleep oznacza, że ​​wątek nie powinien nic robić (poza spaniem), więc dodatkowa praca nikomu nie przeszkadza”.

– Dokładnie to samo powiedziałeś wcześniej.

„A co z twoim stwierdzeniem: « Nikt nie może zagwarantować, że nić zostanie zatrzymana. Tylko nić może zatrzymać się sama. » Czy możesz to wyjaśnić?”

"Jasne."

„Wcześniej, we wczesnych wersjach Javy, wątki miały metodę stop(). Kiedy ją wywołałeś, JVM faktycznie zatrzymywała wątek. Ale jeśli wątek robił coś poza JVM (na przykład zapisywał do pliku lub wywoływał OS), gdy została przerwana w ten sposób, przerwa spowodowała wiele problemów, takich jak niezamknięte pliki, niewydane zasoby systemowe itp.

„Walne zgromadzenie twórców Javy zdecydowało o usunięciu metody wymuszającego zatrzymywanie wątków. Teraz pozostaje nam tylko ustawić odpowiednią flagę (isInterrupted) i mieć nadzieję, że kod wątku został napisany poprawnie, dzięki czemu ta flaga zostanie przetworzona. Ta flaga jest jak znak, który mówi: „Wątek, przestań, proszę. To bardzo ważne!”. Ale to, czy się zatrzyma, czy nie, to jego własna sprawa.

„Ale co z wyjątkiem InterruptedException?”

„Co jeśli kod działający w tym wątku ma kilka bloków try-catch? Nawet jeśli gdzieś wystąpi wyjątek InterruptedException, zdecydowanie nie ma gwarancji, że jakiś try-catch go nie złapie i nie zapomni o nim. Nie ma więc gwarancji, że wątek się zatrzyma”.

„Inną rzeczą jest to, że wątki są już uważane za programowanie dość niskiego poziomu. Ale o tym opowiem następnym razem”.

„Nie jesteś Ellie - jesteś Szeherezada!”

„Więc, Amigo! Czy wszystko w bieżącej lekcji jest jasne?”

"Tak."

"Dobrze."