Le concept de filetage Java <br /> Contrairement à la plupart des autres langages informatiques, Java prend en charge la programmation multithread dans intégrée.
Un programme multithread contient deux pièces ou plus qui s'exécutent simultanément. Chacune de ces parties du programme est appelée thread, et chaque thread a un chemin d'exécution indépendant. Par conséquent, le multithreading est une forme spéciale de multitâche.
Vous devez connaître le multitâche car il est en fait pris en charge par tous les systèmes d'exploitation modernes. Cependant, il existe deux types distincts de multitâche: basés sur des processus et basés sur le thread. Il est très important de comprendre les différences entre les deux.
Pour de nombreux lecteurs, le multitâche basé sur les processus est une forme plus familière. Un processus est essentiellement un programme d'exécution. Par conséquent, le multitâche basé sur des processus est caractérisé en permettant à votre ordinateur d'exécuter deux programmes ou plus simultanément. Par exemple, le multitâche basé sur des processus vous permet d'exécuter le compilateur Java simultanément lors de l'utilisation d'un éditeur de texte. Dans le multitâche basé sur des processus, un programme est la plus petite unité de code attribuée par le planificateur.
Dans un environnement multitâche basé sur des threads, les threads sont la plus petite unité d'exécution. Cela signifie qu'un programme peut effectuer des fonctions de deux tâches ou plus simultanément. Par exemple, un éditeur de texte peut formater du texte lors de l'impression. Par conséquent, les programmes multi-processus gèrent les «grandes images», tandis que les programmes multi-threads gèrent les détails.
Les programmes multithread nécessitent moins de dépenses administratives que les programmes multiproces. Les processus sont des tâches poids lourds qui nécessitent leur propre espace d'adressage indépendant. La communication entre les processus est coûteuse et restreinte. La transformation entre les processus est également très coûteuse. Les fils, en revanche, sont des joueurs légers. Ils partagent le même espace d'adresse et partagent le même processus ensemble. La communication inter-thread est bon marché et la conversion inter-thread est également à faible coût. Lorsqu'un programme Java utilise un environnement de traitement des tâches multiprocesse, le programme multi-processus n'est pas contrôlé par Java, tandis que le multi-lancement est contrôlé par Java.
Le multithreading vous aide à rédiger des programmes efficaces avec une utilisation maximale du processeur, car le temps inactif est réduit au minimum. Ceci est crucial pour les environnements d'interconnexion de réseau interactifs en Java, car le temps libre est public. Par exemple, le taux de transmission des données du réseau est bien inférieur à la capacité de traitement de l'ordinateur, et la vitesse de lecture et d'écriture des ressources du système de fichiers locales est beaucoup plus faible que celle du processeur. . Dans un environnement traditionnel unique, votre programme doit attendre que chacune de ces tâches se termine avant d'effectuer l'étape suivante - bien que le CPU ait beaucoup de temps libre. Multithreading vous permet d'obtenir et de tirer le meilleur parti de ce temps libre.
Modèle de filetage java
Le système d'exécution Java s'appuie sur des threads à bien des égards, et toutes les conceptions de bibliothèque de classe prennent en compte le multithreading. En fait, Java utilise des threads pour rendre l'environnement entier asynchrone. Cela aide à réduire la partie invalide en empêchant le gaspillage des boucles de processeur.
Pour mieux comprendre les avantages d'un environnement multithread, il peut être comparé à ses contrôles. La méthode de traitement d'un système unique consiste à utiliser une méthode de boucle d'événement appelée sondage. Dans ce modèle, le contrôle unique fonctionne dans une boucle infinie, interrogeant une séquence d'événements pour déterminer quoi faire ensuite. Une fois que le dispositif de sondage renvoie un signal selon lequel le fichier réseau est prêt à être lu, le contrôle de planification de la boucle d'événement gère le gestionnaire d'événements approprié. Jusqu'à ce que le gestionnaire d'événements revienne, aucun autre événement ne se produit dans le système. Cela gaspille le temps du processeur. Cela entraîne une partie du programme pour occuper exclusivement le système et empêcher l'exécution d'autres événements. En général, dans un environnement unique, lorsqu'un thread bloque (blocs, suspend l'exécution) en attendant des ressources, l'ensemble du programme cesse de fonctionner.
L'avantage du multithreading Java est qu'il annule le mécanisme de boucle / d'interrogation principale. Un fil peut être interrompu sans affecter d'autres parties du programme. Par exemple, le temps d'inactivité généré lorsqu'un thread lit les données du réseau ou attend la saisie de l'utilisateur peut être utilisé ailleurs. Multithreading permet à une boucle en direct de dormir une seconde dans chaque espace de cadre sans faire une pause dans l'ensemble du système. Il y a un blocage de thread dans un programme Java, un seul thread est suspendu et les autres threads continuent de s'exécuter.
Les fils existent dans plusieurs États. Le fil peut être en cours d'exécution. Il peut fonctionner tant que vous obtenez du temps de processeur. Le thread en cours d'exécution peut être suspendu et interrompre temporairement son exécution. Un fil suspendu peut être repris, ce qui lui permet de continuer à courir à partir de l'endroit où il s'est arrêté.
À tout moment, le fil peut se terminer, ce qui interrompt immédiatement son fonctionnement. Une fois terminée, le fil ne peut pas être restauré.
Priorité du thread
Java priorise chaque thread pour déterminer comment traiter le thread par rapport aux autres threads. La priorité du thread est un entier qui détaille la relation prioritaire entre les threads. En tant que valeur absolue, la priorité est dénuée de sens; Au lieu de cela, la priorité du thread est utilisée pour déterminer quand passer d'un thread en cours d'exécution à un autre. C'est ce qu'on appelle le "commutateur de contexte". Les règles qui déterminent l'occurrence de la conversion de contexte sont simples:
Les threads peuvent automatiquement abandonner le contrôle. Dans le cas des E / S indécis, le sommeil ou le blocage se fait par des concessions explicites. En vertu de cette hypothèse, tous les autres threads sont détectés et le fil de priorité le plus élevé prêt à s'exécuter est accordé au CPU.
Les threads peuvent être préemptés par des fils de haute priorité. Dans ce cas, le fil à faible priorité n'abandonne pas activement, le processeur est juste occupé en premier - quoi qu'il fasse - le processeur est occupé par le fil à haute priorité. Fondamentalement, une fois qu'un thread haute priorité est sur le point de s'exécuter, il s'exécute. C'est ce qu'on appelle le multitâche prioritaire.
La situation est un peu compliquée lorsque deux fils de la même priorité rivalisent pour les cycles du processeur. Pour les systèmes d'exploitation comme Windows 98, les threads avec une priorité égale divisent automatiquement le temps en mode boucle. Pour d'autres systèmes d'exploitation, tels que Solaris 2.x, les threads prioritaires sont automatiquement abandonnés par rapport à leurs pairs. Si ce n'est pas le cas, d'autres threads ne s'exécuteront pas.
AVERTISSEMENT: La conversion de contexte des threads de priorité inférieure sur différents systèmes d'exploitation peut générer des erreurs.
Synchronisation
Étant donné que le multithreading introduit un comportement asynchrone dans votre programme, il doit y avoir des moyens d'améliorer la synchronisation lorsque vous en avez besoin. Par exemple, si vous voulez que deux threads communiquent entre eux et partagent une structure de données complexe, comme une séquence de listes liées, vous avez besoin d'un moyen de vous assurer qu'ils ne sont pas conflictuels les uns avec les autres. Autrement dit, vous devez empêcher un thread de rédiger des données tandis qu'un autre thread lit les données de la liste liée. À cette fin, Java implémente une autre méthode basée sur l'ancien modèle de synchronisation inter-processus: moniteur. Le processus de gestion est un mécanisme de contrôle défini d'abord par Carhoare.
Vous pouvez considérer le processus de gestion comme une petite boîte qui ne contrôle qu'un seul fil. Une fois qu'un fil entre dans un tuyau, tous les filetages doivent attendre que le fil quitte le tuyau. De cette façon, la direction peut être utilisée pour empêcher la manipulation des ressources partagées par plusieurs threads.
De nombreux systèmes multi-threads considèrent le processus de gestion comme un objet que le programme doit clairement faire référence et opérer. Java fournit une solution claire. Il n'y a pas de classe "Monitor"; à la place, chaque objet a sa propre manipulation implicite, qui est automatiquement chargée lorsque la méthode de synchronisation de l'objet est appelée. Une fois qu'un thread est inclus dans une méthode de synchronisation, aucun autre thread ne peut appeler la méthode de synchronisation du même objet. Cela vous permet d'écrire du code multi-thread très clair et concis, car le support de synchronisation est intégré à la langue.
Livraison de messages
Après avoir divisé le programme en plusieurs threads, vous devez définir la connexion entre chaque thread. Lorsque vous planifiez dans la plupart des autres langues, vous devez compter sur le système d'exploitation pour établir une communication inter-thread. Cela augmentera certainement le coût. Cependant, Java fournit une façon propre et à faible coût de parler entre Multithreads - en appelant des méthodes prédéfinies que tous les objets ont. Le système de messagerie de Java permet à un thread de saisir une méthode synchrone d'un objet, puis d'attendre là-bas jusqu'à ce que d'autres threads le notent explicitement.
Classe de threads et interface Runnable
Le système multi-thread de Java est basé sur la classe de threads, ses méthodes et son interface de co-composition à exécuter. La classe de threads résume l'exécution des threads. Étant donné que vous ne pouvez pas vous référer directement à l'état du thread en cours d'exécution, vous devez le traiter via son proxy, donc l'instance de thread est générée. Pour créer un nouveau thread, votre programme doit étendre le thread ou implémenter l'interface Runnable.
La classe de threads définit plusieurs méthodes pour aider à gérer les threads. Les méthodes utilisées dans ce chapitre sont présentées dans le tableau: