Cet article est un résumé de l'utilisation de base du multithreading Java.
Cet article expliquera l'utilisation de base du multithreading Java à partir des aspects suivants:
Comment utiliser le multithreading
Deux façons de démarrer un fil
Java fournit deux façons d'utiliser le multi-threading. L'une consiste à écrire une classe pour hériter du thread, puis à écraser la méthode d'exécution, puis à appeler la méthode de démarrage pour démarrer le thread. À l'heure actuelle, cette classe exécutera le code dans la méthode d'exécution dans la façon dont un autre thread. Une autre façon consiste à écrire une classe pour implémenter l'interface Runnable, puis à implémenter la méthode d'interface, puis à créer un objet de thread, à utiliser la classe qui implémente l'interface Runnable en tant que paramètre de construction, à la transmettre dans l'objet thread, et enfin l'objet thread appelle la méthode de démarrage.
La méthode de démarrage ici est une méthode avec la fonction de démarrage, qui rappelle en interne la méthode d'exécution. Par conséquent, ce n'est que lorsque la méthode de démarrage est appelée un autre thread sera démarré, la méthode d'exécution sera appelée directement, ou s'exécutera dans le même thread, plutôt que d'exécuter dans un autre thread
De plus, la méthode de démarrage indique simplement à la machine virtuelle que le thread peut être démarré, ce qui signifie que le thread est à l'état prêt, mais cela ne signifie pas que l'appel à démarrer s'exécutera immédiatement. Cela nécessite d'attendre que le JVM décide quand exécuter le thread. En d'autres termes, s'il y a deux threads A et B, les appels A commencent d'abord et que les appels B commencent plus tard, cela ne signifie pas que le thread A s'exécute en premier, et le thread B s'exécute plus tard. Tout cela est déterminé par le JVM et peut être considéré comme un démarrage aléatoire.
Ci-dessous, nous utilisons du code réel pour illustrer deux façons de démarrer les threads:
Le premier type est un fil héritant
La classe publique ExampleThread étend Thread {@Override public void run () {super.run (); System.out.println ("Ceci est un examplethead hérité de Thread"); }}Le code de test peut être trouvé dans la classe ExampleThReadTest dans le répertoire de test
Une autre façon, implémente l'interface runnable
classe publique Examplerunable implémente Runnable {public void run () {System.out.println ("Ceci est la classe qui implémente l'interface Runnable"); }}Pour le code de test, vous pouvez voir la classe ExamplerUnableTest dans le répertoire de test.
Comment obtenir des informations sur le multithreading
Après avoir commencé le multi-threading, nous espérons obtenir des informations sur le fil démarré via certaines API. JDK nous fournit une méthode de classe de thread pour obtenir des informations sur le fil.
Obtenez le nom du fil
Ces méthodes sont des méthodes internes de thread, nous pouvons donc appeler ces méthodes de deux manières. La première est que lorsque notre classe hérite du thread pour utiliser le multi-thread, nous pouvons l'utiliser pour l'appeler. Une autre façon consiste à appeler ces méthodes via thread.currentThread (). Cependant, ces deux méthodes sont différentes dans différents scénarios d'utilisation.
Examinons brièvement l'utilisation de deux méthodes.
Le premier thread.currentThread () est utilisé, le code est le suivant:
classe publique ExampleCurrentThread étend Thread {public exampleCurrentThread () {System.out.println ("Imprimer de la méthode du constructeur:" + thread.currentThread (). getName ()); } @Override public void run () {super.run (); System.out.println ("Imprimer de la méthode de run:" + thread.currentThread (). GetName ()); }}Le code de test est le suivant:
classe publique ExampleCurrentThreadTest étend TestCase {public void testinit () lève l'exception {exampleCurrentThread Thread = new ExampleCurrentThread (); } public void testrun () lève une exception {exampleCurrentThread Thread = new ExampleCurrentThread (); thread.start (); Thread.Sleep (1000); }}Les résultats sont les suivants:
Impression de la méthode du constructeur: Impression de la méthode MainRun: Impression de la méthode de construction Thread-0: Main
Pourquoi utilisons-nous thread.currentThread () à l'intérieur examplecurrentThread pour afficher que la méthode de construction est imprimée comme principal, car thread.currentThread () renvoie les informations que le segment de code est appelée par ce thread. Il est évident que la méthode de construction est exécutée par le thread principal et que la méthode d'exécution est exécutée par le fil que nous avons commencé par nous-mêmes. Parce qu'il n'est pas nommé, c'est le thread-0 par défaut.
Ensuite, nous jetons un coup d'œil à l'héritage du fil et à l'appeler avec cela.
classe publique complexcurrentThread étend Thread {public complexcurrentThread () {System.out.println ("begin ================="); System.out.println ("thread.currentThread (). GetName =" + thread.currentThread (). GetName ()); System.out.println ("this.getName () =" + this.getName ()); System.out.println ("end ==========================================);} @Override public Void Run () {super.run (); System.out.Println (" Run Begin ============ "); System.out.println ("thread.currentThread (). GetName =" + thread.currentThread (). GetName ());Le code de test est le suivant:
classe publique ComplexCurrentThreadTest étend TestCase {public void testRun () lève une exception {complexcurrentThread Thread = new complexCurrentThread (); thread.setName ("byHieg"); thread.start (); Thread.Sleep (3000); }}Les résultats sont les suivants:
Begin =========== thread.currentThread (). getName = MainThis.getName () = Thread-0end ==================== Run Begin ======= Thread.currentThread ().
Tout d'abord, lors de la création de l'objet, le constructeur est toujours exécuté par le thread principal, donc thread.currentThread () obtient le nom du thread principal, mais cette méthode fait référence à l'objet qui appelle la méthode, c'est-à-dire les informations sur le thread de ComplexCurrentThread. Il n'y a pas encore de nom setName, c'est donc le nom par défaut. Ensuite, la méthode d'exécution est soit thread.currentThread (), soit cela renvoie des informations de thread avec l'ensemble de noms ByHieg.
Donc thread.currentThread fait référence aux informations de thread qui exécutent spécifiquement ce bloc de code. Le constructeur est exécuté par Main, et la méthode d'exécution est quel thread démarre et quel thread exécute l'exécution. À partir de ce point de vue, les informations que cela peuvent obtenir est inexacte, car si nous exécutons ce.GetName () dans Run, mais la méthode d'exécution est lancée par un autre fil, nous ne pouvons pas obtenir les informations de la nouvelle ville exécutant la méthode Run via ce.getName. Et seules les classes qui héritent du thread peuvent avoir des méthodes telles que GetName, qui est une catastrophe pour les langues de fonctionnalité de Java qui n'ont pas plusieurs héritages. Pour toutes les informations sur les threads que nous voulons obtenir par la suite, nous utilisons thread.currentThread () pour appeler l'API.
Obtenez l'ID du fil
Appelez GetId pour obtenir l'identification unique du fil. C'est la même chose que l'utilisation de GetName ci-dessus. Il n'y a rien à dire. Vous pouvez regarder directement ExempleIdThread et sa classe de test ExempleIdThreadTest.
Déterminez si le fil survit
La fonction de la méthode Isalive () est de tester si le thread est actif. Le soi-disant état actif signifie que le fil a été démarré mais n'a pas terminé. Autrement dit, après le début du fil, il est considéré comme vivant.
Jetons un coup d'œil à des exemples spécifiques:
classe publique AliveThread étend Thread {@Override public void run () {super.run (); System.out.println ("est-il vivant dans la méthode d'exécution" + "" + thread.currentThread (). Isalive ()); }}La méthode de test est la suivante:
classe publique AliveThreadTest étend TestCase {public void testrun () lève une exception {aliveThread Thread = new AliveThread (); System.out.println ("begin ==" + thread.isalive ()); thread.start (); Thread.Sleep (1000); System.out.println ("end ==" + thread.isalive ()); Thread.Sleep (3000); }}Les résultats sont les suivants:
begin == si le trueend dans la fausse méthode == false
Nous pouvons constater qu'avant le début, le fil est considéré comme insurvé, puis quand il fonctionne, il est vivant. Lorsque la méthode d'exécution est exécutée, elle est considérée comme insultée.
Comment arrêter un fil
Déterminer si le thread s'est terminé
JDK fournit quelques méthodes pour déterminer si le thread est terminé - est interrompu () et interrompu ()
Comment arrêter les fils
Il s'agit d'une méthode plus importante pour obtenir des informations sur le thread, car elle est liée à la méthode de terminaison des threads. Permettez-moi d'abord de parler de plusieurs façons de résilier les fils:
Je ne parlerai pas du premier, la deuxième méthode stop () a été abandonnée car les raisons suivantes peuvent se produire:
Pour des exemples spécifiques, vous pouvez voir StoplockThread et sa classe de test StoplockThreadTest
Le troisième type est la méthode de terminaison actuellement recommandée, appelant l'interruption, puis déterminant s'il faut se terminer dans la méthode d'exécution. Il existe deux façons de juger de la résiliation. L'un est la méthode statique interrompue () de la classe de thread, et l'autre est la méthode du membre du thread est Interrupted (). Il existe une différence entre ces deux méthodes. La première méthode réinitialisera automatiquement l'état. Si interrompu () est appelé deux fois de suite, s'il est faux la première fois, la deuxième fois qu'il doit être vrai. Et Isinterrupted () ne le fera pas.
Les exemples sont les suivants:
classe publique ExempleInterruptThread étend Thread {@Override public void run () {super.run (); essayez {pour (int i = 0; i <50000000; i ++) {if (interrompu ()) {System.out.println ("C'est déjà un état d'arrêt, je veux sortir"); Jetez une nouvelle interruption ("stop ......"); } System.out.println ("i =" + (i + 1)); }} catch (InterruptedException e) {System.out.println ("STOP en douceur"); }}}Le code de test est le suivant:
classe publique ExempleInterruptThreadTest étend TestCase {public void TestRun () lève l'exception {ExampleInterRruptThread Thread = new ExempleInterRruptThread (); thread.start (); Thread.Sleep (1000); thread.interrupt (); }}La quatrième méthode est la même que la troisième. La seule différence est de remplacer l'exception lancée dans le code ci-dessus par retour. J'aime toujours lancer des exceptions. Il existe de nombreuses formes de traitement ici, telles que l'impression d'informations, la fermeture ou la capture de la ressource, puis la jette à nouveau sur la couche supérieure.
Notez que l'exception que nous avons lancée ci-dessus est une exception interrompue. Ici, nous parlons brièvement des raisons pour lesquelles cette exception peut être générée. Dans le cas du sommeil du thread d'origine, appelez l'interruption pour terminer le thread, ou terminez d'abord le fil, puis laissez le fil dormir.
Comment faire une pause
Les deux méthodes suivantes sont fournies dans le JDK pour la pause et la restauration des fils.
Ces deux méthodes sont des méthodes abandonnées comme la méthode d'arrêt, et leur utilisation est la même que celle des fils d'arrêt, de suspension brutale et de restauration des fils. Les principales raisons pour lesquelles ces deux méthodes sont abandonnées sont:
Quelques autres usages de fils
Certains autres usages de base des fils sont les suivants:
Concessions de fil
JDK fournit la méthode de rendement () pour faire en sorte que le fil abandonne la ressource CPU actuelle et le donne à d'autres tâches pour occuper le temps du processeur, mais c'est aussi une chose aléatoire. Il est possible qu'il prenne le temps de temps juste après avoir abandonné les ressources.
Pour des exemples spécifiques, veuillez vous référer à ExampleyEieldThread et à sa classe de test ExampleyEieldThreadTest
Définir la priorité des threads
Nous pouvons définir la priorité des threads pour laisser le CPU autant que possible pour envoyer les ressources d'exécution aux threads avec une priorité plus élevée. Java établit 1-10 10 niveaux de priorité, et il existe trois variables statiques pour fournir trois niveaux de priorité:
/ ** * La priorité minimale qu'un fil peut avoir. * / public final static int min_priority = 1; / ** * La priorité par défaut qui est attribuée à un thread. * / public final static int norm_priority = 5; / ** * La priorité maximale qu'un fil peut avoir. * / public final static int max_priority = 10;
Nous pouvons définir la priorité du thread via SetPriority, et pouvons passer directement en trois variables statiques pour l'appel, ou passer directement dans les numéros 1-10. Après le réglage, le thread aura des priorités différentes. Que se passe-t-il si nous ne fixons pas la priorité?
La priorité des fils est héritée. Si nous commençons le fil B dans le fil A, AB a la même priorité. Généralement, lorsque nous démarrons un fil dans le thread principal, nous avons une priorité cohérente avec le fil principal. La priorité du thread principal est de 5 par défaut.
Voici quelques règles de priorité:
Gardien de fil
Le JDK fournit une méthode SetDaemon pour définir un fil pour devenir un fil de démon. La caractéristique des fils de démon est qu'après que d'autres threads non aléatoires soient exécutés, les fils de démon seront automatiquement détruits. Un exemple typique est le recycleur GC.
Pour plus de détails, vous pouvez voir ExampledaEmonThread et ExampledaEmthThreadTest.
Résumer
Cet article résume principalement certains usages de base des threads Java et est inclus dans le deuxième article sur la sécurité et la synchronisation des fils.
Ce qui précède est tout le contenu de cet article. J'espère que le contenu de cet article sera d'une aide à l'étude ou au travail de chacun. J'espère également soutenir plus Wulin.com!