CodeGym/Blog Java/Aleatoriu/Multithreading: ce fac metodele clasei Thread
John Squirrels
Nivel
San Francisco

Multithreading: ce fac metodele clasei Thread

Publicat în grup
Bună! Astăzi vom continua să vorbim despre multithreading. Să examinăm clasa Thread și ce fac câteva dintre metodele sale. Când am studiat anterior metodele de clasă, de obicei am scris doar acest lucru: <numele metodei> -> <ce face metoda>. Multithreading: Ce fac metodele clasei Thread - 1Acest lucru nu va funcționa cu Threadmetodele lui :) Au o logică mai complexă pe care nu o veți putea da seama fără câteva exemple.

Metoda Thread.start().

Să începem prin a ne repeta. După cum probabil vă amintiți, puteți crea un fir făcând ca clasa dvs. să moștenească clasa Threadși suprascriind run()metoda. Dar nu va începe de la sine, desigur. Pentru a face acest lucru, numim start()metoda obiectului nostru. Multithreading: Ce fac metodele clasei Thread - 2Să ne amintim exemplul din lecția anterioară:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Notă: Pentru a începe un thread, trebuie să apelațistart()metoda specială mai degrabă decâtrun()metoda! Aceasta este o eroare ușor de făcut, mai ales când începeți să studiați multithreading. În exemplul nostru, dacă apelațirun()metoda de 10 ori în loc destart(), veți obține acest lucru:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Uitați-vă la rezultatele programului nostru: Fir executat: Fir-0 Fir executat: Fire-1 Fire executat: Thread-2 Thread executat: Thread-3 Thread executat: Thread-4 Thread executat: Thread-5 Thread executat: Thread-6 Thread executat: Thread-7 Thread executat: Thread-8 Thread executat: Thread-9 Uită-te la ordinea de ieșire: Totul se întâmplă în ordine perfectă. Ciudat, nu? Nu suntem obișnuiți cu asta, pentru că știm deja că ordinea în care sunt pornite și executate firele este determinată de un intelect superior din interiorul sistemului nostru de operare: planificatorul de fire. Poate doar am avut noroc? Desigur, nu este vorba despre noroc. Puteți verifica acest lucru rulând programul de încă câteva ori. Problema este că apelulrun()metoda direct nu are nimic de-a face cu multithreading. În acest caz, programul va fi executat pe firul principal, același fir care execută metoda main(). Pur și simplu imprimă succesiv 10 rânduri pe consolă și atât. 10 fire nu au fost începute. Deci, amintiți-vă acest lucru în viitor și verificați-vă în mod constant. Dacă doriți ca run()metoda să fie apelată, apelați start(). Să mergem mai departe.

Metoda Thread.sleep().

Pentru a suspenda execuția firului curent pentru un timp, folosim sleep()metoda. Multithreading: Ce fac metodele clasei Thread - 3Metoda sleep()ia un număr de milisecunde ca argument, ceea ce indică timpul necesar pentru a pune firul în stare de repaus.
public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - How long did I sleep? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " seconds");

   }
}
Ieșire consolă: - Cât timp am dormit? - 3 secunde Notă: metoda sleep()este statică: dorește firul curent. Adică cel în curs de executare. Iată un alt punct important: un fir adormit poate fi întrerupt. În acest caz, programul aruncă un InterruptedException. Vom lua în considerare un exemplu mai jos. Apropo, ce se întâmplă după ce firul se trezește? Va continua să fie executat chiar de unde a rămas? Nu. După ce un fir se trezește, adică timpul trecut ca argument pentru Thread.sleep()a trecut, acesta trece la rulabilstat. Dar, acest lucru nu înseamnă că programatorul de fire îl va rula. Este posibil să dea preferință unui alt fir care nu dorm și să permită firului nostru proaspăt trezit să-și continue activitatea puțin mai târziu. Asigurați-vă că rețineți acest lucru: a te trezi nu înseamnă a continua munca imediat!

Metoda Thread.join().

Multithreading: Ce fac metodele clasei Thread - 4Metoda join()suspendă execuția firului curent până când se termină un alt fir. Dacă avem 2 fire, t1și t2, și scriem
t1.join()
atunci t2nu va începe până nu t1își va termina munca. Metoda join()poate fi folosită pentru a garanta ordinea de execuție a firelor de execuție. Să luăm în considerare modul în care join()funcționează metoda în următorul exemplu:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Thread started: " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Thread " + getName() + " is finished.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /* The second thread (t2) will start running only after the first thread (t1)
       is finished (or an exception is thrown) */
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       // The main thread will continue running only after t1 and t2 have finished
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("All threads have finished. The program is finished.");

   }
}
Am creat o ThreadExampleclasă simplă. Sarcina sa este să afișeze un mesaj că firul a început, să adormi timp de 5 secunde și apoi să raporteze că lucrarea este finalizată. Bucată de tort. Logica principală este în Mainclasă. Uită-te la comentarii: folosim join()metoda pentru a gestiona cu succes ordinea de execuție a firelor. Dacă vă amintiți cum am început acest subiect, ordinea de execuție este gestionată de planificatorul de fire. Rulează fire la propria discreție: de fiecare dată într-un mod diferit. Aici folosim metoda pentru a garanta că t1firul de execuție va fi mai întâi pornit și executat, apoit2thread și numai după aceea va continua firul principal al programului. Trecând peste. În programele reale, veți găsi adesea situații în care va trebui să întrerupeți execuția unui fir. De exemplu, firul nostru rulează, dar așteaptă un anumit eveniment sau o anumită condiție. Dacă apare, atunci firul se oprește. Probabil că ar avea sens dacă ar exista un fel de stop()metodă. Dar nu este atât de simplu. Cândva, Java avea de fapt o Thread.stop()metodă și permitea întreruperea unui fir. Dar a fost ulterior eliminat din biblioteca Java. Îl puteți găsi în documentația Oracle și puteți vedea că este marcat ca depreciat. De ce? Pentru că a oprit firul fără să facă altceva. De exemplu, firul ar putea să lucreze cu date și să schimbe ceva. Apoi, în mijlocul lucrării sale, a fost tăiat brusc și fără ceremonie de stop()metodă. Fără o închidere adecvată, nici eliberarea de resurse, nici măcar gestionarea erorilor - nu a existat nimic din toate acestea. Pentru a exagera puțin, stop()metoda pur și simplu a distrus totul în calea ei. Era ca și cum ai trage cablul de alimentare de la priză pentru a opri computerul. Da, poți obține rezultatul dorit. Dar toată lumea știe că, după câteva săptămâni, computerul nu îți va mulțumi că ai tratat-o ​​așa. De aceea, logica de întrerupere a firelor de execuție s-a schimbat în Java și acum folosește o interrupt()metodă specială.

Metoda Thread.interrupt().

Ce se întâmplă dacă interrupt()metoda este apelată pe un fir? Exista 2 posibilitati:
  1. Dacă obiectul a fost în starea de așteptare, de exemplu, din cauza metodelor joinsau sleep, atunci așteptarea va fi întreruptă și programul va arunca un InterruptedException.
  2. Dacă firul de execuție era într-o stare de funcționare, atunci interruptedsteagul boolean va fi setat pe obiect.
Dar trebuie să verificăm valoarea acestui steag pe obiect și să finalizam corect munca pe cont propriu! De aceea Threadclasa are boolean isInterrupted()metoda. Să revenim la exemplul de ceas care a fost într-o lecție din cursul de bază. Pentru comoditate, am simplificat ușor:
public class Clock extends Thread {

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

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("The thread was interrupted");
               break;
           }
           System.out.println("Tick");
       }
   }
}
În acest caz, ceasul este pornit și începe să ticăie în fiecare secundă. În a 10-a secundă, întrerupem firul ceasului. După cum știți deja, dacă firul pe care încercăm să-l întrerupem se află într-una dintre stările de așteptare, rezultatul este un InterruptedException. Aceasta este o excepție verificată, astfel încât să o putem prinde cu ușurință și să ne executăm logica pentru a finaliza programul. Și tocmai asta am făcut. Iată rezultatul nostru: Tick Tick Tick Tick Tick Tick Tick Tick Firul a fost întrerupt. Aceasta se încheie introducerea noastră la Threadcele mai importante metode ale clasei. Noroc!
Comentarii
  • Popular
  • Nou
  • Vechi
Trebuie să fii conectat pentru a lăsa un comentariu
Această pagină nu are încă niciun comentariu