JavaRush /Blog Java /Random-FR /Multithreading : à quoi servent les méthodes de classe Th...

Multithreading : à quoi servent les méthodes de classe Thread

Publié dans le groupe Random-FR
Bonjour! Aujourd'hui, nous continuons à parler de multithreading. Jetons un coup d'œil à la classe Thread et au fonctionnement de ses différentes méthodes. Auparavant, lorsque nous étudiions les méthodes de classe, nous l'écrivions le plus souvent simplement ainsi : « nom de la méthode » -> « ce qu'elle fait ».
Multithreading : que font les méthodes de la classe Thread - 1
Cela ne fonctionnera pas avec les méthodes Thread :) Leur logique est plus compliquée et sans plusieurs exemples, il est impossible de comprendre.

Méthode Thread.start()

Commençons par la répétition. Comme vous vous en souvenez probablement, vous pouvez créer un thread en héritant de votre classe Threadet en remplaçant la méthode qu'elle contient run(). Mais bien sûr, cela ne démarrera pas tout seul. Pour ce faire, nous appelons la méthode sur notre objet start(). Multithreading : que font les méthodes de la classe Thread - 2Rappelons l'exemple du cours précédent :
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();
       }
   }
}
Attention : pour démarrer un fil de discussion, vous devez appeler la méthode spécialestart(), pas la méthoderun()! C’est une erreur facile à commettre, surtout lors de l’apprentissage du multithreading pour la première fois. Si dans notre exemple vous appelez une méthode sur un objet 10 foisrun()au lieu destart(), le résultat sera comme ceci :
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 exécuté Thread-1 thread exécuté Thread-2 thread exécuté Thread-3 thread exécuté Thread-4 thread exécuté Thread-5 thread exécuté Thread-6 thread exécuté Thread-7 thread exécuté Thread-8 thread exécuté Thread-9 thread exécuté Regardez la séquence de sortie : tout se passe strictement dans l'ordre. Étrange, non ? Nous ne sommes pas habitués à cela, car nous savons déjà que l'ordre dans lequel les threads sont lancés et exécutés est déterminé par la superintelligence de notre système d'exploitation - le planificateur de threads. Peut-être que j'ai juste eu de la chance ? Bien sûr, ce n’est pas une question de chance. Vous pouvez le vérifier en exécutant le programme plusieurs fois. Le fait est que l’appel direct d’une méthoderun()n’a rien à voir avec le multithreading. Dans ce cas, le programme sera exécuté dans le thread principal - celui dans lequel la méthode est exécutéemain(). Il affichera simplement 10 lignes séquentiellement sur la console et c'est tout. Aucun fil de discussion 10 ne démarrera. Par conséquent, n’oubliez pas pour l’avenir et vérifiez-vous constamment. Si vous voulez que cela soit faitrun(), appelez-lestart(). Allons-nous en.

Méthode Thread.sleep()

Pour suspendre l'exécution du thread en cours pendant un certain temps, utilisez le sleep(). Multithreading : que font les méthodes de la classe Thread - 3La méthode sleep()prend en paramètre le nombre de millisecondes, c'est-à-dire le temps pendant lequel le thread doit être mis en veille.
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 + " секунды");

   }
}
Résultat de la console : - Combien de temps ai-je dormi ? - 3 secondes Attention : la méthode sleep()est statique : elle met le thread en cours en veille. C'est-à-dire celui qui fonctionne en ce moment. Autre nuance importante : le flux en état de sommeil peut être interrompu. Dans ce cas, une exception se produira dans le programme InterruptedException. Nous examinerons un exemple ci-dessous. Au fait, que se passe-t-il une fois que le fil se « réveille » ? Pourra-t-il immédiatement poursuivre son exécution là où elle s’est arrêtée ? Non. Une fois le thread réveillé (lorsque le temps passé en argument expire Thread.sleep()), il entre dans l' état exécutable . Cependant, cela ne signifie pas que le planificateur de threads l'exécutera. Il est fort possible qu'il privilégie un autre fil « non endormi », et notre fil « fraîchement réveillé » continuera à fonctionner un peu plus tard. N’oubliez pas : « se réveiller ne signifie pas continuer à travailler à la seconde même ! »

Méthode Thread.join()

Multithreading : que font les méthodes de la classe Thread - 4La méthode join()suspend l'exécution du thread en cours jusqu'à ce qu'un autre thread se termine. Si nous avons 2 threads, t1et t2, et que nous écrivons -
t1.join()
t2ne commencera pas à fonctionner tant que t1 n'aura pas terminé son travail. La méthode join()peut être utilisée pour garantir la séquence d’exécution des threads. Regardons le travail join()à l'aide d'un exemple :
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 работу, программа завершена");

   }
}
Nous avons créé une classe simple ThreadExample. Sa tâche est d'afficher un message sur l'écran concernant le début des travaux, puis de s'endormir pendant 5 secondes et à la fin d'informer de la fin des travaux. Rien de compliqué. La logique principale est contenue dans la classe Main. Regardez les commentaires : en utilisant la méthode, join()nous contrôlons avec succès la séquence d'exécution des threads. Si vous vous souvenez du début du sujet, c'est le planificateur de threads qui a fait cela. Il les lançait à sa guise : différemment à chaque fois. Ici, en utilisant la méthode, nous nous sommes assurés que le thread serait d'abord lancé et exécuté t1, puis le thread t2, et seulement après eux le thread principal d'exécution du programme. Poursuivre. Dans les programmes réels, vous rencontrerez souvent des situations où vous devrez interrompre l'exécution d'un thread. Par exemple, notre thread est en cours d’exécution, mais il attend qu’un certain événement ou une certaine condition soit rempli. Si cela se produit, cela s'arrête. Ce serait probablement logique s'il existait une méthode comme stop(). Pourtant, tout n’est pas si simple. Il était une fois une méthode Thread.stop()en Java qui existait réellement et qui permettait d'interrompre le travail d'un thread. Mais plus tard, il a été supprimé de la bibliothèque Java. Vous pouvez le rechercher dans la documentation Oracle et constater qu'il est marqué comme obsolète . Pourquoi? Parce qu’il a simplement arrêté le flux sans aucun travail supplémentaire. Par exemple, un thread pourrait travailler avec des données et y modifier quelque chose. Puis il a été brusquement assommé stop()au milieu du travail - et c'était tout. Il n'y a eu aucun arrêt correct, aucune libération de ressources, ni même aucune gestion des erreurs - rien de tout cela ne s'est produit. La méthode stop(), pour exagérer, a tout simplement détruit sur son passage. Son fonctionnement peut être comparé à la façon dont quelqu’un débranche la fiche de la prise pour éteindre un ordinateur. Oui, vous pouvez obtenir le résultat souhaité. Mais tout le monde comprend que dans quelques semaines, l'ordinateur ne dira pas « merci » pour cela. Pour cette raison, la logique d'interruption des threads en Java a été modifiée et une méthode spéciale est désormais utilisée - interrupt().

Méthode Thread.interrupt()

Que se passe-t-il si vous appelez une méthode interrupt() sur un thread ? Il y a 2 options :
  1. Si l'objet était en attente à ce moment-là, par exemple, joinou sleep, l'attente sera interrompue et le programme lancera InterruptedException.
  2. Si le thread était en état de fonctionnement à ce moment-là, l'indicateur booléen de l'objet sera défini interrupted.
Mais nous devrons vérifier l'objet pour la valeur de ce drapeau et terminer le travail correctement nous-mêmes ! Pour cela, la classe Threaddispose d'une méthode spéciale - boolean isInterrupted(). Revenons à l'exemple d'horloge du cours principal. Pour plus de commodité, c'est légèrement simplifié :
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");
       }
   }
}
Dans notre cas, l’horloge démarre et recommence à tourner toutes les secondes. A la 10ème seconde, nous interrompons le flux de l'horloge. Comme vous le savez déjà, si le thread que nous essayons d'interrompre est dans l'un des états d'attente, cela entraîne InterruptedException. Ce type d'exception est une exception vérifiée, elle peut donc être facilement interceptée et notre logique de fin de programme exécutée. C'est ce que nous avons fait. Voici notre résultat : Tik Tik Tik Tik Tik Tik Tik Tik Tik Tik Le travail du fil a été interrompu, ceci conclut notre introduction aux principales méthodes de la classe Thread. Pour consolider vos connaissances, vous pouvez regarder cette conférence vidéo sur le multithreading :
cela constituera un excellent matériel supplémentaire ! A la fin, après un aperçu des méthodes, il indique exactement ce que nous allons parcourir ensuite dans le cours :) Bonne chance !
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION