Problèmes que le multithreading résout en Java
Essentiellement, le multithreading Java a été inventé pour résoudre deux problèmes principaux :-
Effectuez plusieurs actions en même temps.
Dans l'exemple ci-dessus, différents threads (c'est-à-dire des membres de la famille) ont effectué plusieurs actions en parallèle : faire la vaisselle, aller au magasin, plier des objets.
Un exemple plus « programmeur » peut être donné. Imaginez que vous disposez d'un programme avec une interface utilisateur. Lorsque vous cliquez sur le bouton Continuer, certains calculs devraient avoir lieu dans le programme et l'utilisateur devrait voir l'écran d'interface suivant. Si ces actions sont effectuées séquentiellement, après avoir cliqué sur le bouton « Continuer », le programme se bloquera simplement. L'utilisateur verra le même écran avec un bouton « Continuer » jusqu'à ce que tous les calculs internes soient terminés et que le programme atteigne la partie où l'interface commencera à être dessinée.
Eh bien, attendons quelques minutes !
Nous pouvons également refaire notre programme ou, comme disent les programmeurs, le « paralléliser ». Laissez les calculs nécessaires être effectués dans un thread et le rendu de l'interface dans un autre. La plupart des ordinateurs disposent de suffisamment de ressources pour cela. Dans ce cas, le programme ne sera pas « stupide » et l'utilisateur se déplacera sereinement entre les écrans de l'interface sans se soucier de ce qui se passe à l'intérieur. Cela ne gêne pas :)
-
Accélérez les calculs.
Tout est beaucoup plus simple ici. Si notre processeur a plusieurs cœurs et que la plupart des processeurs sont désormais multicœurs, notre liste de tâches peut être résolue en parallèle par plusieurs cœurs. Évidemment, si nous devons résoudre 1 000 problèmes et que chacun d'eux est résolu en une seconde, un cœur traitera la liste en 1 000 secondes, deux cœurs en 500 secondes, trois en un peu plus de 333 secondes, et ainsi de suite.
Thread
. Autrement dit, pour créer et exécuter 10 threads, vous aurez besoin de 10 objets de cette classe. Écrivons l'exemple le plus simple :
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
Pour créer et lancer des threads, nous devons créer une classe et en hériter du java.lang
. Thread
et remplacez la méthode qu'il contient run()
. Le dernier est très important. C'est dans la méthode que run()
nous prescrivons la logique que notre thread doit exécuter. Maintenant, si nous créons une instance MyFirstThread
et l'exécutons, la méthode run()
imprimera une ligne avec son nom sur la console : la méthode getName()
imprime le nom « système » du thread, qui est attribué automatiquement. Mais en fait, pourquoi « si » ? Créons et testons !
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
Sortie de la console : Je suis Thread ! Je m'appelle Thread-2, je suis Thread ! Je m'appelle Thread-1, je suis Thread ! Je m'appelle Thread-0, je suis Thread ! Je m'appelle Thread-3, je suis Thread ! Je m'appelle Thread-6, je suis Thread ! Je m'appelle Thread-7, je suis Thread ! Je m'appelle Thread-4, je suis Thread ! Je m'appelle Thread-5, je suis Thread ! Je m'appelle Thread-9, je suis Thread ! Je m'appelle Thread-8. Nous créons 10 threads (objets) MyFirstThread
dont nous héritons Thread
et les lançons en appelant la méthode de l'objet start()
. Après avoir appelé une méthode , start()
sa méthode commence à fonctionner run()
et la logique qui y est écrite est exécutée. Attention : les noms des sujets ne sont pas dans l'ordre. C'est assez étrange, pourquoi n'ont-ils pas été exécutés à tour de rôle : Thread-0
, Thread-1
, Thread-2
et ainsi de suite ? C’est exactement un exemple de cas où la pensée standard « séquentielle » ne fonctionnera pas. Le fait est que dans ce cas, nous émettons uniquement des commandes pour créer et lancer 10 threads. L'ordre dans lequel ils doivent être lancés est décidé par le planificateur de threads : un mécanisme spécial à l'intérieur du système d'exploitation. La manière exacte dont il est structuré et selon quels principes il prend ses décisions est un sujet très complexe, et nous n'y reviendrons pas maintenant. La principale chose à retenir est que le programmeur ne peut pas contrôler la séquence d’exécution des threads. Pour prendre conscience de la gravité de la situation, essayez d’exécuter la méthode main()
de l’exemple ci-dessus plusieurs fois. Sortie de la deuxième console : je suis Thread ! Je m'appelle Thread-0, je suis Thread ! Je m'appelle Thread-4, je suis Thread ! Je m'appelle Thread-3, je suis Thread ! Je m'appelle Thread-2, je suis Thread ! Je m'appelle Thread-1, je suis Thread ! Je m'appelle Thread-5, je suis Thread ! Je m'appelle Thread-6, je suis Thread ! Je m'appelle Thread-8, je suis Thread ! Je m'appelle Thread-9, je suis Thread ! Je m'appelle Thread-7 Troisième sortie de la console : je suis Thread ! Je m'appelle Thread-0, je suis Thread ! Je m'appelle Thread-3, je suis Thread ! Je m'appelle Thread-1, je suis Thread ! Je m'appelle Thread-2, je suis Thread ! Je m'appelle Thread-6, je suis Thread ! Je m'appelle Thread-4, je suis Thread ! Je m'appelle Thread-9, je suis Thread ! Je m'appelle Thread-5, je suis Thread ! Je m'appelle Thread-7, je suis Thread ! Je m'appelle Thread-8
Problèmes créés par le multithreading
Dans l'exemple des livres, vous avez vu que le multithreading résout des problèmes assez importants et que son utilisation accélère le travail de nos programmes. Dans de nombreux cas – plusieurs fois. Mais ce n’est pas pour rien que le multithreading est considéré comme un sujet complexe. Après tout, si elle est mal utilisée, elle crée des problèmes au lieu de les résoudre. Quand je dis « créer des problèmes », je ne parle pas de quelque chose d’abstrait. Le multithreading peut causer deux problèmes spécifiques : les blocages et les conditions de concurrence critique. Un blocage est une situation dans laquelle plusieurs threads attendent des ressources occupées les uns par les autres, et aucun d'entre eux ne peut continuer à s'exécuter. Nous en parlerons davantage dans les prochaines conférences, mais pour l'instant cet exemple suffira : imaginez que le thread-1 travaille avec un objet-1 et que le thread-2 travaille avec un objet-2. Le programme s'écrit ainsi :- Thread-1 cessera de fonctionner avec l'objet-1 et passera à l'objet-2 dès que Thread-2 cessera de fonctionner avec l'objet 2 et passera à l'objet-1.
- Thread-2 cessera de fonctionner avec l'objet-2 et passera à l'objet-1 dès que Thread-1 cessera de fonctionner avec l'objet 1 et passera à l'objet-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();
}
}
}
Imaginez maintenant que le programme soit responsable du fonctionnement d'un robot qui prépare la nourriture ! Thread-0 sort les œufs du réfrigérateur. Le flux 1 allume la cuisinière. Stream-2 sort une poêle à frire et la met sur le feu. Le flux 3 allume un feu sur la cuisinière. Le flux 4 verse de l'huile dans la poêle. Le flux 5 casse les œufs et les verse dans la poêle. Le Stream 6 jette les coquilles à la poubelle. Stream-7 retire les œufs brouillés finis du feu. Potok-8 met des œufs brouillés dans une assiette. Stream-9 fait la vaisselle. Regardez les résultats de notre programme : Thread-0 exécuté Thread-2 thread exécuté Thread-1 thread exécuté Thread-4 thread exécuté Thread-9 thread exécuté Thread-5 thread exécuté Thread-8 thread exécuté Thread-7 thread exécuté Thread-7 thread exécuté -3 Thread-6 thread exécuté. Le script est-il amusant ? :) Et tout cela parce que le fonctionnement de notre programme dépend de l'ordre dans lequel les threads sont exécutés. A la moindre violation de la séquence, notre cuisine se transforme en enfer, et un robot devenu fou détruit tout autour d'elle. C'est également un problème courant dans la programmation multithread, dont vous entendrez parler plus d'une fois. À la fin de la conférence, je voudrais vous recommander un livre sur le multithreading.
GO TO FULL VERSION