JavaRush /Java Blog /Random-TL /Multithreading: Ano ang Ginagawa ng Thread Class Methods

Multithreading: Ano ang Ginagawa ng Thread Class Methods

Nai-publish sa grupo
Kamusta! Ngayon ay patuloy nating pinag-uusapan ang tungkol sa multithreading. Tingnan natin ang klase ng Thread at kung paano gumagana ang ilang pamamaraan nito. Dati, kapag pinag-aralan namin ang mga pamamaraan ng klase, kadalasan ay isinulat namin ito nang ganito: "pangalan ng pamamaraan" -> "kung ano ang ginagawa nito."
Multithreading: kung ano ang ginagawa ng mga pamamaraan ng klase ng Thread - 1
Hindi ito gagana sa mga pamamaraan ng Thread :) Ang kanilang lohika ay mas kumplikado, at walang ilang mga halimbawa imposibleng maunawaan.

Thread.start() method

Magsimula tayo sa pag-uulit. Tulad ng malamang na natatandaan mo, maaari kang lumikha ng isang thread sa pamamagitan ng pagmamana ng iyong klase mula sa klase Threadat pag-override sa pamamaraan sa loob nito run(). Ngunit, siyempre, hindi ito magsisimula sa sarili nitong. Upang gawin ito, tinatawag namin ang pamamaraan sa aming object start(). Multithreading: kung ano ang ginagawa ng mga pamamaraan ng klase ng Thread - 2Tandaan natin ang halimbawa mula sa nakaraang lecture:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Выполнен поток " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Mangyaring tandaan: upang magsimula ng isang thread, dapat mong tawagan ang espesyal na paraanstart(), hindi angrun()! Ito ay isang madaling pagkakamali, lalo na sa unang pag-aaral ng multithreading. Kung sa aming halimbawa ay tinawag mo ang pamamaraan ng bagayrun()sa halip nastart(), ang resulta ay magiging ganito:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Thread-0 thread executed Thread-1 thread executed Thread-2 thread executed Thread-3 thread executed Thread-4 thread executed Thread-5 thread executed Thread-6 thread executed Thread-7 thread executed Thread-8 thread executed Thread-9 thread executed Tingnan ang pagkakasunud-sunod ng output: lahat ay napupunta nang mahigpit sa pagkakasunud-sunod. Kakaiba, tama? Hindi kami sanay dito, dahil alam na namin na ang pagkakasunud-sunod kung saan ang mga thread ay inilunsad at naisakatuparan ay tinutukoy ng superintelligence sa loob ng aming operating system - ang thread scheduler. Baka sinuwerte lang ako? Siyempre, hindi ito isang bagay ng swerte. Maaari mong i-verify ito sa pamamagitan ng pagpapatakbo ng programa nang ilang beses pa. Ang punto ay ang direktang pagtawag sa isang pamamaraanrun()ay walang kinalaman sa multithreading. Sa kasong ito, ang programa ay isasagawa sa pangunahing thread - ang isa kung saan ang pamamaraan ay pinaandarmain(). Maglalabas lamang ito ng 10 linya nang sunud-sunod sa console at iyon lang. Walang 10 thread ang magsisimula. Samakatuwid, tandaan para sa hinaharap at patuloy na suriin ang iyong sarili. Kung nais mong gawin itorun(), tawagan itostart(). Mag-move on na tayo.

Thread.sleep() method

Upang i-pause ang execution ng kasalukuyang thread nang ilang panahon, gamitin ang sleep(). Multithreading: kung ano ang ginagawa ng mga pamamaraan ng klase ng Thread - 3Kinukuha ng pamamaraan sleep()bilang parameter ang bilang ng mga millisecond, iyon ay, ang oras kung saan kailangang matulog ang thread.
public class Main {

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

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");

   }
}
Output ng console: - Gaano katagal ako nakatulog? - 3 segundo Pakitandaan: ang pamamaraan sleep()ay static: pinapatulog nito ang kasalukuyang thread. Iyon ay, ang isa na gumagana sa sandaling ito. Isa pang mahalagang nuance: ang daloy sa estado ng pagtulog ay maaaring magambala. Sa kasong ito, magkakaroon ng pagbubukod sa programa InterruptedException. Titingnan natin ang isang halimbawa sa ibaba. Sa pamamagitan ng paraan, ano ang mangyayari pagkatapos ng thread na "nagising"? Magpapatuloy ba ito kaagad sa pagpapatupad nito mula sa kung saan ito tumigil? Hindi. Matapos magising ang thread—kapag nag-expire ang oras bilang argumento Thread.sleep()—pumasok ito sa runnable na estado . Gayunpaman, hindi ito nangangahulugan na ang thread scheduler ang tatakbo nito. Ito ay lubos na posible na ito ay magbibigay ng kagustuhan sa ilang iba pang "hindi natutulog" na thread, at ang aming "bagong gising" na thread ay patuloy na gagana sa ibang pagkakataon. Siguraduhing tandaan: "Ang paggising ay hindi nangangahulugang patuloy na magtrabaho sa sandaling iyon!"

Thread.join() method

Multithreading: kung ano ang ginagawa ng mga pamamaraan ng klase ng Thread - 4Ang pamamaraan join()ay sinuspinde ang pagpapatupad ng kasalukuyang thread hanggang sa makumpleto ang isa pang thread. Kung mayroon kaming 2 thread, t1at t2, at sumulat kami -
t1.join()
t2hindi magsisimulang magtrabaho hangga't hindi nakumpleto ng t1 ang gawain nito. join()Maaaring gamitin ang pamamaraan upang matiyak ang pagkakasunud-sunod ng pagpapatupad ng mga thread. Tingnan natin ang gawain join()gamit ang isang halimbawa:
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Начало работы потока " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Поток " + getName() +  " завершил работу.");
   }
}


public class Main {

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

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

       t1.start();


 /*Второй поток t2 начнет выполнение только после того, How будет завершен
       (or бросит исключение) первый поток - t1*/
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       //Главный поток продолжит работу только после того, How t1 и t2 завершат работу
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("Все потоки закончor работу, программа завершена");

   }
}
Gumawa kami ng isang simpleng klase ThreadExample. Ang gawain nito ay magpakita ng isang mensahe sa screen tungkol sa pagsisimula ng trabaho, pagkatapos ay matulog sa loob ng 5 segundo at sa dulo ay ipaalam ang tungkol sa pagkumpleto ng trabaho. Walang kumplikado. Ang pangunahing lohika ay nakapaloob sa klase Main. Tingnan ang mga komento: gamit ang pamamaraan, join()matagumpay naming kinokontrol ang pagkakasunud-sunod ng pagpapatupad ng mga thread. Kung naaalala mo ang simula ng paksa, ginawa ito ng scheduler ng thread. Inilunsad niya ang mga ito sa kanyang sariling paghuhusga: naiiba sa bawat oras. Dito, gamit ang pamamaraan, tiniyak namin na una ang thread ay ilulunsad at isasagawa t1, pagkatapos ay ang thread t2, at pagkatapos lamang sa kanila ang pangunahing thread ng pagpapatupad ng programa. Sige lang. Sa totoong mga programa, madalas kang makakatagpo ng mga sitwasyon kung kailan kailangan mong matakpan ang pagpapatupad ng ilang thread. Halimbawa, ang aming thread ay tumatakbo, ngunit ito ay naghihintay para sa isang tiyak na kaganapan o kundisyon na matugunan. Kung mangyari ito, hihinto ito. Ito ay marahil ay lohikal kung mayroong ilang paraan tulad ng stop(). Gayunpaman, ang lahat ay hindi gaanong simple. Noong unang panahon, ang isang pamamaraan Thread.stop()sa Java ay aktwal na umiral at pinapayagan kang matakpan ang gawain ng isang thread. Ngunit kalaunan ay inalis ito sa library ng Java. Maaari mong hanapin ito sa dokumentasyon ng Oracle at makita na ito ay minarkahan bilang hindi na ginagamit . Bakit? Dahil pinahinto lang nito ang daloy nang walang karagdagang trabaho. Halimbawa, ang isang thread ay maaaring gumana sa data at magbago ng isang bagay sa loob nito. Pagkatapos ay bigla siyang na-knock out stop()sa kalagitnaan ng trabaho - at iyon lang. Walang tamang pagsara, walang pagpapalaya ng mga mapagkukunan, kahit na paghawak ng error - wala sa mga ito ang nangyari. Ang pamamaraan stop(), upang palakihin, ay sinira lamang ang lahat sa landas nito. Ang operasyon nito ay maihahambing sa kung paano kinukuha ng isang tao ang plug mula sa socket upang patayin ang isang computer. Oo, makakamit mo ang ninanais na resulta. Ngunit naiintindihan ng lahat na sa loob ng ilang linggo ang computer ay hindi magsasabi ng "salamat" para dito. Para sa kadahilanang ito, ang lohika para sa pag-abala sa mga thread sa Java ay binago, at ngayon ay isang espesyal na paraan ang ginagamit - interrupt().

Thread.interrupt() method

Ano ang mangyayari kung tumawag ka ng paraan interrupt() sa isang thread ? Mayroong 2 pagpipilian:
  1. Kung ang bagay ay nasa kalagayan ng paghihintay sa sandaling iyon, halimbawa, joino sleep, ang paghihintay ay maaantala at ang programa ay magtapon ng InterruptedException.
  2. Kung gumagana ang thread sa sandaling iyon, itatakda ang boolean flag ng object interrupted.
Ngunit kailangan nating suriin ang bagay para sa halaga ng watawat na ito at kumpletuhin nang tama ang gawain sa ating sarili! Para sa layuning ito, ang klase Threaday may espesyal na pamamaraan - boolean isInterrupted(). Bumalik tayo sa halimbawa ng orasan mula sa pangunahing kurso ng panayam. Para sa kaginhawahan, ito ay bahagyang pinasimple:
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("Работа потока была прервана");
               break;
           }
           System.out.println("Tik");
       }
   }
}
Sa aming kaso, ang orasan ay nagsisimula at nagsisimulang mag-tick bawat segundo. Sa ika-10 segundo naaantala namin ang daloy ng orasan. Tulad ng alam mo na, kung ang thread na sinusubukan naming matakpan ay nasa isa sa mga status ng paghihintay, nagreresulta ito sa InterruptedException. Ang ganitong uri ng exception ay isang checked exception, kaya madali itong mahuli at maisakatuparan ang aming logic sa pagwawakas ng programa. Iyon ang ginawa namin. Narito ang aming resulta: Tik Tik Tik Tik Tik Tik Tik Tik Tik Tik Naantala ang gawain ng thread. Ito ang nagtatapos sa aming pagpapakilala sa mga pangunahing pamamaraan ng klase Thread. Upang pagsama-samahin ang iyong kaalaman, maaari mong panoorin ang video lecture na ito tungkol sa multithreading:
ito ay magsisilbing mahusay na karagdagang materyal! Sa dulo, pagkatapos ng isang pangkalahatang-ideya ng mga pamamaraan, eksaktong sinasabi nito kung ano ang susunod nating pagdadaanan sa kurso :) Good luck!
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION