1. Fil et processus
1. Quelle est la différence entre le thread et le processus:
Un thread fait référence à une unité d'exécution qui peut exécuter le code de programme pendant l'exécution. Dans la langue java, les threads ont quatre états: exécuter, prêt, suspendre et fin.
Un processus fait référence à un programme exécuté. Les fils sont également devenus des processus légers lorsqu'ils ont quelque chose à faire. Ils ont la plus petite unité d'exécution du programme. Un processus peut avoir plusieurs threads. Chaque thread partage l'espace d'alimentation interne du programme (segments de code, segments de données et espace de tas) et certaines ressources au niveau du processus (telles que les fichiers ouverts), mais chaque thread a son propre espace.
2. Pourquoi utiliser le multi-processus ? <Br /> Il existe principalement les aspects suivants au niveau du système d'exploitation:
- L'utilisation du multi-lancement peut réduire le temps de réponse du programme. Si une opération prend du temps ou est coincée dans une longue attente, le programme ne répondra pas aux opérations telles que la souris et le clavier. Après avoir utilisé le multi-threading, ce thread chronophage peut être alloué à un thread séparé pour l'exécution, ce qui rend le programme meilleure interactivité.
- La création de threads et la commande de la surcharge sont moins coûteuses par rapport aux processus, tandis que le multithreading est très efficace dans le partage de données.
- Les ordinateurs multi-CPU ou multi-core ont la possibilité d'exécuter des multi-threads. Si un seul processus est utilisé, les ressources informatiques ne seront pas réutilisées, entraînant un énorme gaspillage de ressources. L'utilisation de multithreading sur des ordinateurs multi-CPU peut améliorer l'utilisation du processeur.
- L'utilisation de multithreading peut simplifier la structure du programme et faciliter la compréhension et la maintenance.
2. Création de threads <br /> Il existe généralement trois méthodes d'implémentation multi-lancement, et les deux premiers sont les méthodes les plus couramment utilisées:
1. Hériter de la classe de thread et remplacer la méthode run ()
Le thread est essentiellement une instance qui implémente l'interface Runnable. Il convient de noter qu'après avoir appelé la méthode start (), il n'exécute pas immédiatement de code multithread, mais fait fonctionner le thread. Quand exécuter du code multi-thread est déterminé par le système d'exploitation.
Voici les étapes principales:
(1) Définissez la sous-classe de la classe de thread et remplacez la méthode d'exécution de la classe. Le corps de la méthode de la méthode d'exécution représente la tâche que le thread souhaite accomplir. Par conséquent, la méthode run () est appelée le corps d'exécution.
(2) Créez une instance de la sous-classe de thread, c'est-à-dire créer un objet de thread.
(3) Appelez la méthode start () de l'objet de thread pour démarrer le thread.
classe publique TestThread étend Thread {public void run () {System.out.println ("Hello World"); } public static void main (String [] args) {thread mthread = new TestThread (); mthread.start (); }} 2. Implémentez l'interface Runnable et implémentez la méthode run () de l'interface
Voici les étapes principales:
(1) Personnalisez la classe et implémentez l'interface Runnable, et implémentez la méthode run ().
(2) Créez une instance de la sous-classe de thread et instanciez l'objet thread avec l'objet qui implémente l'interface Runnable en tant que paramètre.
(3) Méthode START () du thread d'appel pour démarrer le thread.
classe publique TestRunnable implémente Runnable {public void run () {System.out.println ("Hello World"); }} classe publique TestRunnable {public static void main (String [] args) {testrunnable mTestrunnable = new TestRunnable (); Thread mthread = nouveau thread (mTestrunnable); mthread.start (); }} 3. Implémentez l'interface appelée et remplacez la méthode Call ()
L'interface callable est en fait une classe fonctionnelle dans le cadre de l'exécuteur. L'interface appelable est similaire à l'interface Runnable, mais fournit des fonctions plus puissantes que Runnable, qui se manifestent principalement dans les 3 points suivants:
(1) Callable peut fournir une valeur de retour une fois la tâche acceptée et que Runnable ne peut pas fournir cette fonction.
(2) La méthode Call () dans Callable peut lancer des exceptions, tandis que la méthode Run () de Runnable ne peut pas lancer des exceptions.
(3) L'exécution de Calable peut obtenir un futur objet. L'objet futur représente le résultat du calcul d'Ibrahimovic, et il fournit une méthode pour vérifier si le calcul est terminé. Étant donné que le fil appartient à un modèle de calcul asynchrone, il est impossible d'obtenir la valeur de retour de la fonction à partir d'autres threads. Dans ce cas, Future peut être utilisé pour surveiller la méthode Call () lorsque le thread cible appelle la méthode Call (). Cependant, lorsque la méthode Future Get () est appelée pour obtenir le résultat, le thread actuel bloque et connaîtra le résultat de retour de la méthode Call ().
classe publique TestCallable {// Créer des threads classe publique STATIQUE classe MyTestCallable implémente callable {public String Call () lève une exception {RETUN "Hello World"; }} public static void main (string [] args) {myTestCallable mmyTestCallable = new myTestCallable (); ExecutorService mexEcutOrService = exécutor Futur mfuture = mexEcutOrService.Submit (mmyTestCallable); essayez {// en attente de la fin du thread et renvoie le résultat System.out.println (mfuture.get ()); } catch (exception e) {e.printStackTrace (); }}}Le résultat de sortie du programme ci-dessus est: Hello World
Parmi ces trois méthodes, il est généralement recommandé d'implémenter l'interface runnable. La raison en est la suivante: la classe de thread définit une variété de méthodes qui peuvent être réécrites par des classes dérivées, mais seule la méthode run () doit être réécrite, ce qui réalise la fonction principale de ce thread, qui est également la méthode requise pour implémenter l'interface Runnable. Deuxièmement, une classe doit être héritée lorsqu'elle doit être renforcée ou modifiée. Par conséquent, s'il n'est pas nécessaire de remplacer d'autres méthodes de la classe de threads, il est préférable d'implémenter l'interface Runnable dans ce cas.
3. Interruption Thread <Br /> Le thread se terminera lorsque la méthode Run () du thread exécute la dernière instruction du corps de la méthode et revient en exécutant l'instruction RETOUR, ou lorsqu'une exception qui n'est pas prise dans la méthode n'est pas capturée. Il y avait une méthode d'arrêt dans les versions antérieures de Java, que d'autres threads pouvaient appeler pour terminer le thread, mais cette méthode a maintenant été obsolète.
La méthode d'interruption peut être utilisée pour demander la terminaison du thread. Lorsqu'un thread appelle la méthode d'interruption, l'état d'interruption du thread sera défini. Ceci est le drapeau booléen qu'aucun fil n'a. Chaque fil doit vérifier ce drapeau de temps en temps pour déterminer si le fil est interrompu.
Pour savoir si le thread est défini, vous pouvez appeler thread.currentThread (). IsInterrupted ():
while (! thread.currentThread (). isInterrupted ()) {faire quelque chose} Cependant, si un fil est bloqué, l'état d'interruption ne peut pas être détecté. C'est là que l'interruption est générée. Lorsqu'une méthode d'interruption est appelée sur un fil bloqué (appelé sommeil ou attendre). L'appel de blocage sera interrompu par l'interruption de l'Exception.
Si la méthode de sommeil (ou toute autre méthode interruptible) est appelée après chaque itération, la détection ISinterrupted n'est pas nécessaire et inutile. Si la méthode de sommeil est appelée lorsque l'état d'interruption est défini, il ne dormira pas mais effacera l'état et lancera une interruption. Donc, si vous appelez le sommeil dans une boucle, ne détectez pas le statut d'interruption, attrapez simplement l'interruptException.
Dans de nombreux codes publiés, vous constaterez qu'InterruptedException est supprimé à un niveau très bas:
void mytask () {... try {sleep (50)} catch (InterruptedException e) {...}}Ne fais pas ça. Si vous ne pensez pas qu'il y a un avantage dans une prise, il existe deux options raisonnables:
Appel thread.currentThread (). Interrup () dans Catch pour définir l'état d'interruption. Les appelants peuvent le détecter. Une meilleure option consiste à utiliser le lancer InterruptedException pour marquer votre méthode, sans utiliser de blocs d'instruction TRY pour capturer celui terminé. De cette façon, l'appelant peut attraper cette exception:
void mytask () lancer InterruptedException {sleep (50)}4. L'état du fil
(1). Nouveau état (nouveau): un nouvel objet de thread est créé.
(2). Ready State (Runnable): Une fois l'objet de thread créé, d'autres threads appellent la méthode start () de l'objet. Le fil de cet état est situé dans le pool de threads runnable et devient coulable, en attendant d'obtenir les droits d'utilisation du CPU.
(3). État en cours d'exécution: le thread de l'état prêt acquiert le CPU et exécute le code du programme.
(4). État bloqué: l'état bloqué signifie que le fil abandonne les droits d'utilisation du CPU pour une raison quelconque et cesse temporairement de fonctionner. Ce n'est que lorsque le fil entre dans l'état prêt qu'il a une chance d'aller à l'état de course. Il existe trois types de blocage:
- En attente de blocage: le thread en cours d'exécution exécute la méthode Wait () et le JVM mettra le fil dans la piscine d'attente.
- Blocage synchrone: Lorsque le thread en cours d'exécution acquiert le verrou de synchronisation de l'objet, si le verrouillage de synchronisation est occupé par d'autres threads, le JVM mettra le fil dans le pool de verrouillage.
- Autre blocage: Lorsqu'un thread en cours d'exécution exécute la méthode sleep () ou join (), ou émet une demande d'E / S, le JVM définira le thread à un état de blocage. Lorsque l'état de sommeil () a chronométré, join () a attendu que le fil se termine ou l'expression, ou le traitement d'E / S a été terminé, le fil est rentré à l'état prêt.
(5). État mort: le thread a fini d'exécuter ou de quitter la méthode run () en raison d'une exception, et le fil met fin à son cycle de vie.
5. Priorité du fil et fil de démon
1. Priorité du fil
En Java, chaque thread a une priorité et par défaut, un thread hérite de la priorité de sa classe parent. Vous pouvez utiliser la méthode SetPriority pour augmenter ou diminuer toute priorité de thread. La priorité peut être définie sur n'importe quelle valeur entre min_priority (définie comme 1 dans la classe de threads) et Max_priority (définie comme 10 dans la classe de threads). La priorité par défaut des threads est Norm_Priority (défini comme 5 dans la classe de threads).
Essayez de ne pas compter sur la priorité. Si vous voulez vraiment l'utiliser, vous devez éviter une erreur courante que les débutants font. Si plusieurs threads de grande priorité n'entrent pas dans l'état inactif, les threads à faible priorité peuvent ne jamais être exécutés. Chaque fois que le planificateur décide d'exécuter un nouveau thread, il sélectionne d'abord parmi les threads avec priorité, bien que cela affame complètement les fils de faible priorité.
2. Fil de démon
Appel setDaemon (true); convertit le fil en fil de démon. Le seul but des fils de démon est de fournir des services à d'autres threads. Le fil de synchronisation est un exemple. Il envoie régulièrement des signaux à d'autres threads ou efface les threads obsolètes qui indiquent des éléments à cache. Lorsque seuls les fils de démon sont laissés, la machine virtuelle sort, car si seuls les fils de démon sont laissés, il n'est pas nécessaire de continuer à exécuter le programme.
De plus, la collecte des ordures de JVM, la gestion de la mémoire et les autres threads sont des fils de démon. De plus, lorsque vous effectuez des applications de base de données, le pool de connexions de la base de données utilisé contient également de nombreux threads d'arrière-plan, surveillant le nombre de connexions, temps de délai, état, etc.
Ce qui précède concerne la définition, l'état et les propriétés du thread de Java Multithreading. J'espère que cela sera utile à l'apprentissage de tous.