„Bună, Amigo!

"Tot ce este nou este doar ceva vechi pe care l-am uitat. Astăzi voi vorbi despre oprirea thread-urilor. Sper că ați uitat deja cum funcționează metoda interrupt()."

— Da, Ellie, am uitat-o ​​complet.

— Minunat. Atunci îți voi reaminte.

„În Java, dacă cineva dorește să oprească un fir de execuție, el poate semnala acest lucru firului de execuție. Pentru a face acest lucru, trebuie să setați variabila isInterrupted ascunsă a obiectului Thread la true.”

„Fiecare Thread are o metodă de întrerupere(), care este folosită pentru a seta acest flag. Când este apelată metoda de întrerupere (), variabila isInterrupted din interiorul obiectului Thread este setată la adevărat.”

„Și când metoda Thread.sleep() sau join() este apelată pe un fir, metoda verifică dacă steagul isInterrupted este setat pentru firul curent. Dacă acest steag este setat (variabila isInterrupted este egală cu adevărat), atunci metodele lansați o excepție întreruptă ."

„Iată, vă voi aminti de un exemplu vechi:”

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

while (!current.isInterrupted())
{
Thread.sleep(1000);
System.out.println("Tik");
}
}
}
Metoda de rulare a ceasului primește obiectul Thread pentru firul curent.

Clasa Clock scrie cuvântul „Tick” în consolă o dată pe secundă, atâta timp cât variabila isInterrupt a firului curent este falsă.

Când isInterrupt devine adevărat, metoda run se termină.

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

Thread.sleep(10000);
clockThread.interrupt();
}
Firul principal pornește un fir copil (ceasul) care ar trebui să ruleze pentru totdeauna.

Așteptați 10 secunde și anulați sarcina apelând metoda de întrerupere.

Firul principal își termină munca.

Firul ceasului își termină treaba.

„Aici folosim metoda sleep ca parte a unei bucle infinite în metoda run . În buclă, variabila isInterrupt este verificată automat. Dacă un fir apelează metoda sleep , metoda verifică mai întâi dacă isInterrupt este adevărată pentru acel fir unul care a numit metoda sleep). Dacă este adevărat, atunci metoda nu va dormi. În schimb, lansează o excepție InterruptedException ."

„Dar în acest exemplu, verificăm constant variabila isInterrupted în starea buclei.”

„Îmi amintesc că au existat câteva motive pentru care nu am putut folosi această abordare. Îmi poți aminti?”

În primul rând , metoda de rulare nu are întotdeauna o buclă. Metoda poate consta pur și simplu din câteva zeci de apeluri către alte metode. În acest caz, ar trebui să adăugați o verificare isInterrupted înainte de fiecare apel de metodă.”

În al doilea rând , o metodă care implică o mulțime de acțiuni diferite ar putea dura foarte mult timp pentru a fi executată.”

În al treilea rând , aruncarea unei excepții nu înlocuiește verificarea isInterrupted. Este doar o adăugare convenabilă. Excepția aruncată vă permite să derulați rapid stiva de apeluri înapoi la metoda de rulare în sine.”

" În al patrulea rând , metoda somnului este folosită foarte mult. Se dovedește că această metodă utilă este îmbunătățită de o verificare implicită care nu este mai puțin utilă. Parcă nimeni nu a  adăugat cecul în mod specific, dar iată-l.  Acest lucru este super valoros atunci când folosești codul altcuiva și nu poți adăuga singur cecul.”

" În al cincilea rând , verificarea suplimentară nu degradează performanța. Apelarea metodei sleep înseamnă că firul nu ar trebui să facă nimic (cu excepția somnului), așa că munca suplimentară nu deranjează pe nimeni."

— Exact asta ai spus anterior.

„Și cum rămâne cu afirmația ta, „ Nimeni nu poate garanta că un fir va fi oprit. Doar un fir se poate opri singur. ” Poți să explici asta?”

"Sigur."

„Anterior, în versiunile inițiale ale Java, firele de execuție aveau o metodă stop(). Și când ați apelat-o, JVM-ul a oprit firul de execuție. Dar dacă un fir de execuție făcea ceva în afara JVM-ului (de exemplu, scrierea într-un fișier sau apelarea Funcțiile sistemului de operare) când a fost întreruptă în acest fel, întreruperea a cauzat o mulțime de probleme, cum ar fi fișiere neînchise, resurse de sistem neeliberate etc."

„O adunare generală a creatorilor Java a decis să elimine metoda de oprire forțată a firelor de execuție. Acum tot ce putem face este să setăm un anumit steag (este întrerupt) și să sperăm că codul firului de execuție a fost scris corect, astfel încât acest steag să fie procesat. este ca un semn care spune: „Începe, oprește-te, te rog. Este foarte important!’. Dar dacă se oprește sau nu este treaba lui."

— Dar cum rămâne cu Excepția întreruptă?

„Ce se întâmplă dacă codul care rulează pe acest thread are o grămadă de blocuri try-catch? Chiar dacă apare undeva o Excepție întreruptă, cu siguranță nu există nicio garanție că unele try-catch nu îl vor prinde și nu vor uita de el. Deci nu există garanții că firul se va opri.”

„Un alt lucru este că firele de execuție sunt deja considerate programare la nivel destul de scăzut. Dar vă voi spune despre asta data viitoare.”

— Tu nu eşti Ellie — tu eşti Şeherazada!

"Deci, Amigo! Este totul clar în lecția curentă?"

"Da."

"Bun bine."