JavaRush /Java блогу /Random-KY /Multithreading: Thread классынын методдору эмне кылат

Multithreading: Thread классынын методдору эмне кылат

Группада жарыяланган
Салам! Бүгүн биз multithreading жөнүндө сүйлөшүүнү улантабыз. Келгиле, Thread классын жана анын бир нече ыкмаларын кантип иштээрин карап көрөлү. Мурда биз класстык ыкмаларды изилдеп жатканда, биз көбүнчө мындай деп жазчубуз: "методдун аталышы" -> "бул эмне кылат."
Multithreading: Thread классынын ыкмалары эмне кылат - 1
Бул Thread ыкмалары менен иштебейт :) Алардын логикасы татаалыраак жана бир нече мисалсыз аны түшүнүү мүмкүн эмес.

Thread.start() ыкмасы

Келгиле, кайталоодон баштайлы. Эсиңизде болсо керек, классыңызды класстан мурастап Thread, андагы ыкманы жокко чыгаруу менен жип түзө аласыз run(). Бирок, албетте, ал өзүнөн-өзү башталbyte. Бул үчүн, биз an objectибиздеги методду чакырабыз start(). Multithreading: Thread классынын ыкмалары эмне кылат - 2Мурунку лекциядагы мисалды эстейли:
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();
       }
   }
}
Көңүл буруңуз: жипти баштоо үчүн!start()эмес,run()Бул оңой ката кетирүү, өзгөчө көп агымды биринчи жолу үйрөнүүдө. run()Биздин мисалда 10 жолу эмес,an objectтин ыкмасын чакырсаңызstart(), натыйжа төмөнкүдөй болот:
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Thread-0 жип аткарылды Тема-1 жип аткарылды Thread-2 жип аткарылды Тема-3 жип аткарылды Тема-4 жип аткарылды Тема-5 жип аткарылды Тема-6 жип аткарылды Тема-7 жип аткарылды Тема-8 жип аткарылды Thread-8 жип аткарылды Чыгаруунун ырааттуулугун караңыз: баары катуу тартипте жүрөт. Кызык, туурабы? Биз буга көнгөн эмеспиз, анткени жиптердин ишке киришинин жана аткарылышынын тартиби биздин операциялык системабыздын ичиндеги супер интеллект - жип пландоочу тарабынан аныкталаарын билебиз. Балким, мен жөн эле бактылуу болгондурмун? Албетте, бул ийгorктин иши эмес. Бул программаны дагы бир нече жолу иштетүү менен текшере аласыз. Методду түз чакыруунунrun()көп агым менен эч кандай байланышы жок. Бул учурда, программа негизги жипте аткарылат - метод аткарылганmain(). Ал жөн гана консолго ырааттуу 10 сап чыгарат жана ушуну менен бүттү. 10 тема башталbyte. Андыктан келечекти эстеп, өзүңүздү дайыма текшериңиз. Эгер сиз аны аткаргыңыз келсеrun(), аны чакырыңызstart(). Келгиле, уланталы.

Thread.sleep() ыкмасы

Учурдагы жиптин аткарылышын бир нече убакытка тындыруу үчүн, колдонуңуз sleep(). Multithreading: Thread классынын ыкмалары эмне кылат - 3Метод sleep()параметр катары миллисекунддордун санын, башкача айтканда, жипти уктатуу керек болгон убакытты алат.
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 + " секунды");

   }
}
Консолдун чыгышы: - Мен канча убакыт уктадым? - 3 секунд Көңүл буруңуз: ыкма sleep()статикалык: ал учурдагы жипти уктатат. Башкача айтканда, учурда иштеп жаткан. Дагы бир маанилүү нюанс: уйку абалындагы агым үзгүлтүккө учурашы мүмкүн. Бул учурда, программада өзгөчө жагдай пайда болот InterruptedException. Биз төмөндө бир мисалды карап чыгабыз. Баса, жип "ойгонгондон" кийин эмне болот? Ошол замат токтогон жеринен аткарууну улантабы? Жок. Жип ойгонгондон кийин - убакыт аргумент катары өтүп кеткенде - ал иштей турганThread.sleep() абалга кирет . Бирок, бул жип пландоочу аны иштетет дегенди билдирбейт. Ал кандайдыр бир башка “уктабаган” жипке артыкчылык берип, “жаңы ойгонгон” жипибиз бир аз кийинчерээк ишин уланта бериши толук мүмкүн. Эсиңизде болсун: "ойгонуу ошол секундда иштөөнү улантуу дегенди билдирбейт!"

Thread.join() ыкмасы

Многопоточность: что делают методы класса Thread - 4Метод join()учурдагы жиптин аткарылышын башка жип аяктаганга чейин токтотот. Эгерде бизде 2 жип болсо, t1жана t2, жана биз жазабыз -
t1.join()
t2t1 ишин аяктамайынча ишке киришпейт. Метод join()жиптердин аткарылышынын ырааттуулугун камсыз кылуу үчүн колдонулушу мүмкүн. join()Мисал аркылуу ишти карап көрөлү :
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 работу, программа завершена");

   }
}
Биз жөнөкөй класс түздүк ThreadExample. Анын милдети - экранда иштин башталышы жөнүндө билдирүүнү көрсөтүү, андан кийин 5 секунд уктап калуу жана аягында иштин аяктагандыгы жөнүндө маалымат берүү. Эч нерсе татаал эмес. Негизги логика класста камтылган Main. Комментарийлерди караңыз: методду колдонуп, join()жиптердин аткарылышын ийгorктүү көзөмөлдөйбүз. Теманын башталышы эсиңизде болсо, жип пландоочусу муну жасады. Ал аларды өз каалоосу боюнча ишке киргизди: ар бир жолу башкача. t1Бул жерде, методду колдонуп, биз алгач жиптин , андан кийин жиптин t2, андан кийин гана программанын аткарылышынын негизги жипинин ишке киришин жана аткарылышын камсыз кылдык . Уланта бер. Чыныгы программаларда сиз кээ бир жиптин аткарылышын үзгүлтүккө учуратуу керек болгон кырдаалдарга көп туш болосуз. Мисалы, биздин жип иштеп жатат, бирок ал белгилүү бир окуянын же шарттын аткарылышын күтүп жатат. Бул болуп калса, ал токтойт. Мындай ыкма бар болсо, балким, логикалуу болмок stop(). Бирок, баары ушунчалык жөнөкөй эмес. Бир жолу Thread.stop()Java-да бир метод чындыгында бар болчу жана жиптин ишин үзгүлтүккө учуратууга мүмкүндүк берген. Бирок кийинчерээк ал Java китепканасынан алынып салынган. Сиз аны Oracle documentтеринен издеп, анын эскирген деп белгиленгенин көрө аласыз . Неге? Анткени ал эч кандай кошумча жумушсуз эле агымды токтотуп койгон. Мисалы, жип маалыматтар менен иштеп, андагы бир нерсени өзгөртө алат. stop()Анан аны жумуштун ортосунда капысынан нокаут кылып коюшту – ошону менен бүттү. Туура өчүрүү, ресурстарды бошотуу, атүгүл каталарды иштетүү болгон жок - мунун бири да болгон жок. Метод stop()апыртып айтканда, жөн гана өз жолунда баарын жок кылды. Анын иштешин кимдир бирөө компьютерди өчүрүү үчүн розеткадан кантип сууруп алганына салыштырууга болот. Ооба, сиз каалаган натыйжага жете аласыз. Бирок бир нече жумадан кийин компьютер бул үчүн "рахмат" деп айтпай турганын баары түшүнөт. Ушул себептен Java-да жиптерди үзгүлтүккө учуратуу логикасы өзгөртүлдү жана азыр атайын ыкма колдонулат - interrupt().

Thread.interrupt() ыкмасы

Жиптеги ыкманы чакырсаңыз эмне болот interrupt()? 2 вариант бар:
  1. Эгерде an object ошол учурда күтүү абалында болсо, мисалы, joinже sleep, күтүү үзгүлтүккө учурап, программа ыргытат InterruptedException.
  2. Эгерде жип ошол учурда жумушчу абалда болсо, an objectтин логикалык желеги коюлат interrupted.
Бирок an objectти бул желектин баасын текшерип, ишти өзүбүз туура бүтүрүшүбүз керек! Бул үчүн класста Threadатайын метод бар - boolean isInterrupted(). Негизги курстун лекциясынан сааттын мисалына кайрылалы. Ыңгайлуулук үчүн, ал бир аз жөнөкөйлөтүлгөн:
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");
       }
   }
}
Биздин учурда сааттын жебеси секунд сайын башталат жана башталат. 10 секундада сааттын жүрүшүн үзөбүз. Белгилүү болгондой, биз үзүүгө аракет кылып жаткан жип күтүү абалдарынын биринде болсо, бул InterruptedException. Өзгөчөлүктүн бул түрү текшерилген өзгөчөлүк болуп саналат, ошондуктан аны оңой кармап алса болот жана программаны токтотуу логикасы аткарылат. Биз ушундай кылдык. Бул биздин натыйжа: Tik Tik Tik Tik Tik Tik Tik Tik Жиптин иши үзгүлтүккө учурады.Бул биздин класстын негизги ыкмаларына киришүүнү аяктайт Thread. Өзүңүздүн бorмиңизди бекемдөө үчүн сиз көп агым боюнча бул видеолекцияны көрө аласыз:
ал сонун кошумча материал катары кызмат кылат! Акырында, усулдарды карап чыккандан кийин, курста мындан ары эмнеден өтөөрүбүз так айтылат :) Ийгorк!
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION