CodeGym /Java блог /Случаен /Многопоточност: Какво правят методите на класа Thread
John Squirrels
Ниво
San Francisco

Многопоточност: Какво правят методите на класа Thread

Публикувано в групата
здрасти Днес ще продължим да говорим за многопоточност. Нека разгледаме класа Thread и Howво правят някои от неговите методи. Когато преди изучавахме методите на класа, обикновено просто пишехме това: <име на метод> -> <Howво прави методът>. Многопоточност: Какво правят методите на класа Thread - 1Това няма да работи с Threadметодите на :) Те имат по-сложна логика, която няма да можете да разберете без няколко примера.

Методът Thread.start().

Нека започнем, като се повторим. Както вероятно си спомняте, можете да създадете нишка, като накарате вашия клас да наследи класа Threadи замени run()метода. Но няма да започне сам, разбира се. За да направим това, извикваме start()метода на нашия обект. Многопоточност: Какво правят методите на класа Thread - 2Нека си припомним примера от предишния урок:

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();
       }
   }
}
Забележка: За да започнете нишка, трябва да извикате специалнияstart()метод, а неrun()метода! Това е лесна грешка за допускане, особено когато за първи път започнете да изучавате многопоточност. В нашия пример, ако извикатеrun()метода 10 пъти instead ofstart(), ще получите това:

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Вижте резултатите от нашата програма: Изпълнена нишка: Нишка-0 Изпълнена нишка: Нишка-1 Изпълнена нишка: Нишка-2 Изпълнена нишка: Нишка-3 Изпълнена нишка: Нишка-4 Изпълнена нишка: Нишка-5 Изпълнена нишка: Нишка-6 Изпълнена нишка: Нишка-7 Изпълнена нишка: Нишка-8 Изпълнена нишка: Нишка-9 Погледнете реда на изхода: Всичко се случва в перфектен ред. Странно, а? Не сме свикнали с това, защото вече знаем, че редът, в който нишките се стартират и изпълняват, се определя от по-висшия интелект в нашата операционна система: програмата за планиране на нишки. Може би просто сме имали късмет? Разбира се, тук не става въпрос за късмет. Можете да проверите това, като стартирате програмата още няколко пъти. Въпросът е, че се обадете наrun()методът директно няма нищо общо с многопоточността. В този случай програмата ще бъде изпълнена на основната нишка, същата нишка, която изпълнява метода main(). Просто отпечатва последователно 10 реда на конзолата и това е. 10 теми не са стартирани. Така че, запомнете това в бъдеще и постоянно се проверявайте. Ако искате run()методът да бъде извикан, извикайте start(). Да отидем по-нататък.

Методът Thread.sleep().

За да спрем изпълнението на текущата нишка за известно време, използваме sleep()метода. Многопоточност: Какво правят методите на класа Thread - 3Методът sleep()приема брой мorсекунди като аргумент, който показва времето за поставяне на нишката в режим на заспиване.

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");

   }
}
Изход от конзолата: - Колко време спах? - 3 секунди Забележка: методът sleep()е статичен: заспива текущата нишка. Тоест този, който се изпълнява в момента. Ето още един важен момент: спяща нишка може да бъде прекъсната. В този случай програмата хвърля InterruptedException. Ще разгледаме пример по-долу. Между другото, Howво се случва след като нишката се събуди? Ще продължи ли да се изпълнява точно от мястото, където е спряло? Не. След като дадена нишка се събуди, т.е. времето, подадено като аргумент Thread.sleep(), е изтекло, тя преминава в изпълняваемасъстояние. Но това не означава, че планировчикът на нишки ще го изпълни. Възможно е да даде предпочитание на друга неспяща нишка и да позволи на нашата прясно събудена нишка да продължи работата си малко по-късно. Не забравяйте да запомните това: събуждането не означава незабавно продължаване на работата!

Методът Thread.join().

Многопоточност: Какво правят методите на класа Thread - 4Методът join()спира изпълнението на текущата нишка, докато друга нишка завърши. Ако имаме 2 нишки t1и t2, и пишем

t1.join()
след това t2няма да започне, докато t1не приключи работата си. Методът join()може да се използва за гарантиране на реда на изпълнение на нишките. Нека разгледаме How join()работи методът в следния пример:

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.");

   }
}
Създадохме прост ThreadExampleклас. Неговата задача е да покаже съобщение, че нишката е започнала, да заспи за 5 секунди и накрая да отчете, че работата е завършена. Парче торта. Основната логика е в Mainкласа. Вижте коментарите: използваме join()метода за успешно управление на реда на изпълнение на нишките. Ако си спомняте How започнахме тази тема, редът на изпълнение се обработва от планировчика на нишки. Той изпълнява нишки по свое усмотрение: всеки път по различен начин. Тук използваме метода, за да гарантираме, че t1първо ще бъде стартирана и изпълнена нишката, а след товаt2нишка и едва след това ще продължи основната нишка на програмата. Преместване на. В реални програми често ще срещнете ситуации, когато трябва да прекъснете изпълнението на нишка. Например нашата нишка работи, но чака определено събитие or condition. Ако се появи, нишката спира. Вероятно би имало смисъл, ако имаше няHowъв stop()метод. Но не е толкова просто. Имало едно време Java наистина имаше Thread.stop()метод и позволяваше нишката да бъде прекъсната. Но по-късно беше премахнат от библиотеката на Java. Можете да го намерите в documentацията на Oracle и да видите, че е маркиран като остарял. Защо? Защото просто спря нишката, без да прави нищо друго. Например нишката може да работи с данни и да променя нещо. След това по средата на работата си беше внезапно и безцеремонно прекъснат от stop()метода. Без правилно изключване, нито освобождаване на ресурси, нито дори обработка на грешки — нямаше нищо от това. Леко преувеличено, stop()методът просто унищожи всичко по пътя си. Беше като издърпване на захранващия кабел от контакта, за да изключите компютъра. Да, можете да получите желания резултат. Но всеки знае, че след няколко седмици компютърът няма да ви благодари, че се отнасяте към него по този начин. Ето защо логиката за прекъсване на нишки се промени в Java и сега използва специален interrupt()метод.

Методът Thread.interrupt().

Какво се случва, ако interrupt()методът се извика в нишка? Има 2 възможности:
  1. Ако обектът е бил в състояние на изчакване, например поради joinor sleepметодите, тогава изчакването ще бъде прекъснато и програмата ще хвърли InterruptedException.
  2. Ако нишката е била във функциониращо състояние, тогава булевият interruptedфлаг ще бъде зададен на обекта.
Но ние трябва да проверим стойността на този флаг върху обекта и правилно да завършим работата сами! Ето защо 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("The thread was interrupted");
               break;
           }
           System.out.println("Tick");
       }
   }
}
В този случай часовникът се стартира и започва да тиктака всяка секунда. На 10-та секунда прекъсваме нишката на часовника. Както вече знаете, ако нишката, която се опитваме да прекъснем, е в едно от състоянията на изчакване, резултатът е InterruptedException. Това е проверено изключение, така че можем лесно да го хванем и да изпълним нашата логика, за да завършим програмата. И точно това направихме. Ето нашия резултат: Tick Tick Tick Tcik Tick Tick Tick Tick Tick Нишката беше прекъсната. Това завършва въведението ни в Threadнай-важните методи на класа. Късмет!
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION