Problèmes résolus par le multithreading
Le multithreading a en fait été inventé pour atteindre deux objectifs importants :-
Faire plusieurs choses en même temps.
Dans l'exemple ci-dessus, différents threads (membres de la famille) ont effectué plusieurs actions en parallèle : ils ont lavé la vaisselle, sont allés au magasin et ont emballé des choses.
Nous pouvons offrir un exemple plus étroitement lié à la programmation. Supposons que vous ayez un programme avec une interface utilisateur. Lorsque vous cliquez sur "Continuer" dans le programme, certains calculs doivent se produire et l'utilisateur doit voir l'écran suivant. Si ces actions étaient effectuées de manière séquentielle, le programme se bloquerait simplement après que l'utilisateur ait cliqué sur le bouton "Continuer". L'utilisateur verra l'écran avec le bouton "Continuer" jusqu'à ce que le programme effectue tous les calculs internes et atteigne la partie où l'interface utilisateur est actualisée.
Eh bien, je suppose que nous allons attendre quelques minutes !
Ou nous pourrions retravailler notre programme, ou, comme disent les programmeurs, le « paralléliser ». Effectuons nos calculs sur un thread et dessinons l'interface utilisateur sur un autre. La plupart des ordinateurs ont suffisamment de ressources pour le faire. Si nous empruntons cette voie, le programme ne se bloquera pas et l'utilisateur se déplacera en douceur entre les écrans sans se soucier de ce qui se passe à l'intérieur. L'un n'interfère pas avec l'autre :)
-
Effectuez des calculs plus rapidement.
Tout est beaucoup plus simple ici. Si notre processeur a plusieurs cœurs, et la plupart des processeurs le font aujourd'hui, alors plusieurs cœurs peuvent gérer notre liste de tâches en parallèle. Évidemment, si nous devons effectuer 1000 tâches et que chacune prend une seconde, un cœur peut terminer la liste en 1000 secondes, deux cœurs en 500 secondes, trois en un peu plus de 333 secondes, etc.
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
Pour créer et exécuter des threads, nous devons créer une classe, la faire hériter du java.lang . Thread et remplacez sa méthode run() . Cette dernière exigence est très importante. C'est dans la méthode run() que nous définissons la logique d'exécution de notre thread. Maintenant, si nous créons et exécutons une instance de MyFirstThread , la méthode run() affichera une ligne avec un nom : la méthode getName() affiche le nom 'system' du thread, qui est attribué automatiquement. Mais pourquoi parle-t-on timidement ? Créons-en un et découvrons-le !
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
Sortie 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 ! Mon nom est Thread-8 Créons 10 threads ( objets MyFirstThread , qui héritent de Thread ) et démarrons-les en appelant la méthode start() sur chaque objet. Après avoir appelé la méthode start() , la logique de la méthode run() est exécutée. Remarque : les noms des threads ne sont pas dans l'ordre. C'est bizarre qu'ils n'aient pas été séquentiels :, Thread-1 , Thread-2 , etc. En l'occurrence, c'est un exemple d'un moment où la pensée « séquentielle » ne convient pas. Le problème est que nous n'avons fourni que des commandes pour créer et exécuter 10 threads. Le planificateur de threads, un mécanisme spécial du système d'exploitation, décide de leur ordre d'exécution. Sa conception précise et sa stratégie de prise de décision sont des sujets de discussion approfondie dans lesquels nous ne plongerons pas pour le moment. La principale chose à retenir est que le programmeur ne peut pas contrôler l'ordre d'exécution des threads. Pour comprendre la gravité de la situation, essayez d'exécuter la méthode main() dans l'exemple ci-dessus plusieurs fois. Sortie de la console lors de la deuxième exécution : 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 ! Mon nom est la sortie de la console Thread-7 de la troisième exécution : 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 notre exemple avec des livres, vous avez vu que le multithreading résout des tâches très importantes et peut rendre nos programmes plus rapides. Souvent plusieurs fois plus rapide. Mais le multithreading est considéré comme un sujet difficile. En effet, s'il est mal utilisé, il crée des problèmes au lieu de les résoudre. Quand je dis « crée des problèmes », je ne veux pas dire dans un sens abstrait. Le multithreading peut créer deux problèmes spécifiques : les blocages et les conditions de concurrence. Le blocage est une situation où plusieurs threads attendent des ressources détenues les unes par les autres, et aucun d'entre eux ne peut continuer à s'exécuter. Nous en reparlerons dans les leçons suivantes. L'exemple suivant suffira pour l'instant : Imaginez que Thread-1 interagisse avec un Object-1, et que Thread-2 interagisse avec Object-2. De plus, le programme est écrit de telle sorte que :- Thread-1 arrête d'interagir avec Object-1 et passe à Object-2 dès que Thread-2 arrête d'interagir avec Object-2 et passe à Object-1.
- Thread-2 cesse d'interagir avec Object-2 et passe à Object-1 dès que Thread-1 cesse d'interagir avec Object-1 et passe à Object-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();
}
}
}
Imaginez maintenant que le programme est chargé de faire fonctionner un robot qui cuisine des aliments ! Thread-0 sort les œufs du réfrigérateur. Thread-1 allume le poêle. Thread-2 prend une casserole et la pose sur la cuisinière. Thread-3 allume le poêle. Thread-4 verse de l'huile dans la casserole. Thread-5 casse les œufs et les verse dans la casserole. Thread-6 jette les coquilles d'œufs dans la poubelle. Thread-7 supprime les œufs cuits du brûleur. Thread-8 place les œufs cuits dans une assiette. Thread-9 lave la vaisselle. Regardez les résultats de notre programme : Thread exécuté : Thread-0 Thread 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-3 Est-ce une routine comique ? :) Et tout cela parce que le travail de notre programme dépend de l'ordre d'exécution des threads. À la moindre violation de la séquence requise, notre cuisine se transforme en enfer et un robot fou détruit tout ce qui l'entoure. C'est également un problème courant dans la programmation multithread. Vous en entendrez parler plus d'une fois. Pour conclure cette leçon, j'aimerais recommander un livre sur le multithreading. 'Java Concurrency in Practice' a été écrit en 2006, mais n'a pas perdu de sa pertinence. Il est dédié à la programmation Java multithread - des bases aux erreurs et anti-modèles les plus courants. Si vous décidez un jour de devenir un gourou du multithreading, ce livre est une lecture incontournable. A bientôt dans les prochains cours ! :)
GO TO FULL VERSION