Cet article étudie principalement les problèmes liés des fils de fond en Java, comme suit.
Je n'en ai jamais entendu parler auparavant qu'il y a des fils de fond en Java. De manière générale, JVM (Java Virtual Machine) comprend généralement deux types de threads, à savoir le thread utilisateur et le thread d'arrière-plan. Le soi-disant fils de démon fait référence à un fil qui fournit un service commun en arrière-plan lorsque le programme est en cours d'exécution, et ce fil n'est pas une partie indispensable du programme. Par conséquent, lorsque tous les threads non-fond se terminent, c'est-à-dire lorsque les threads utilisateur se terminent, le programme se termine. Dans le même temps, il tuera tous les fils d'arrière-plan dans le processus. Inversement, tant que tous les fils non-fondants sont toujours en cours d'exécution, le programme ne se terminera pas. Il est préférable d'exécuter Main () qu'un thread non-backend.
En fonction de cette fonctionnalité, lorsque tous les threads utilisateur de la machine virtuelle sortent de l'exécution, le thread de démon n'a pas d'objets de service, le JVM sort.
Ceci est expliqué dans le code source JDK.
* Marque ce fil comme un thread {@linkplain #isdaemon}
* ou un thread utilisateur. La machine virtuelle Java sort lorsque le seul
* Les fils en cours d'exécution sont tous des fils de démon.
1. Conditions pour démarrer un fil d'arrière-plan:
/ * La méthode setDaemon () doit être appelée avant de démarrer le thread pour définir ce fil en tant que thread d'arrière-plan. * Dans ce programme, après avoir entré une chaîne, le thread principal cessera d'exécuter * alors il n'y a pas de thread pour l'utilisateur qui peut fonctionner dans le programme. Ainsi, le thread d'arrière-plan sera arrêté * Le JVM sera arrêté, et les lecteurs intéressés peuvent l'essayer vous-même * / classe publique DaemonRunner implémente Runnable {@Override public void run () {while (true) {for (int i = 0; i <3; i ++) {System.out.print STATING ("Daemon Thread" + i);}}}}}}}}}}}}}} public STATIC VOD daemon = nouveau thread (new DaemonRunner ()); daemon.setDaemon (true); daemon.start (); scanner s = new Scanner (System.in); String String = S.NextLine (); runtime.getRuntime (). AddShutdownHook (new Thread () {@ Override public Void run () {super.run (); System.out.Println ("jvm excel {TimeUnit.MilliseConds.Sleep (50);} catch (InterruptedException e) {e.printStackTrace ();}}});}}2. Tous les threads démarrés dans le thread d'arrière-plan appartiennent au thread d'arrière-plan. Bien que vous ne spécifiez pas explicitement que ce sont des threads d'arrière-plan, ce sont en effet des threads d'arrière-plan.
/ * Vous pouvez déterminer si le thread est un thread d'arrière-plan en appelant la méthode isdaemon (). S'il s'agit d'un thread d'arrière-plan, * alors tout fil qu'il crée est automatiquement défini sur le thread d'arrière-plan * Dans cet exemple, le thread de démon est réglé sur le mode d'arrière-plan, puis tire de nombreux threads enfants. Ces threads ne sont pas définis sur le mode d'arrière-plan *, mais ce sont en effet des threads d'arrière-plan. Ensuite, le thread de démon entre dans une boucle infinie et appelle la méthode de rendement dans la boucle * pour remettre le contrôle à d'autres threads ou processus * / class Daemon implémente exécutable {thread privé [] t = nouveau thread [10]; @ Override public void run () {for (int i = 0; i <t.length; i ++) {t [i] = nouveau thread (nouveau thread (new Daemonspawn ()); t [i] .start (); system.out.println ("daemonspawn" + i + "démarré");} pour (int i = 0; i <t.length; i ++) {System.out.println ("t [" + i + "]. {Thread.yield ();}}} classe daemonspawn implémente runnable {@Override public void run () {while (true) {thread.yield ();}}} public class daEmons {public static void main (string [] args) {thread d = new Thread (new net static void main (String [] args) {thread d = new Thread (New Public Static Void Main (String [] args) {thread d = new Thread (nouveau Daemon ()); d.setDaemon (true); d.start (); System.out.println ("d.isdaemon () =" + d.isdaemon ()); try {timeunit.seconds.sleep (1); // laissez le fil dans l'arrière-plan de démarrage obtient un certain temps d'exécution. } catch (InterruptedException e) {e.printStackTrace ();}}}Les résultats de l'exécution finale sont les suivants:
d.isdaemon () = true
Daemonspawn 0started
Daemonspawn 1started
Daemonspawn 2started
Daemonspawn 3started
Daemonspawn 4started
Daemonspawn 5started
Daemonspawn 6started
Daemonspawn 7started
Daemonspawn 8started
Daemonspawn 9started
t [0] .isdaemtrue
t [1] .isdaemtrue
t [2] .isdaemtrue
t [3] .isdaemtrue
t [4] .isdaemtrue
t [5] .isdaemtrue
t [6] .isdaemtrue
t [7] .isdaemontrue
t [8] .isdaemtrue
t [9] .isdaemtrue
3. Spécifiez un objet ThreadFactory en spécifiant Executors.newCachedThreadPool() . De cette façon, nous pouvons également définir le fil que nous voulons démarrer comme thread d'arrière-plan.
/ * Dans cet exemple, pour ce constructeur statique: exécuteurs.NewCachedThreadpool (new DaemonThreadFactory () * Nous pouvons passer dans un objet ThreadFactory, afin que nous puissions définir le thread que nous voulons démarrer comme thread d'arrière-plan via cette méthode * Ceci doit être noté. * / Class Le thread (R); t.setDaemon (true); return t;}} / * Dans cet exemple, dans la méthode principale, la méthode ordinaire dans la méthode principale sera appelée d'abord, System.out.println ("All Dameons a démarré"); "Donc, cette déclaration sera en premier. Sleep, la ligne principale met fin à la course. (InterruptedException e) {System.out.println ("Interrupted");}} public static void main (String [] args) {EMMICRORSERVICE EXEC = exécuteurs.NewCachedThreadpool (new DaemThreadFactory ()); DaemonFromFactory ());} System.out.println ("Tous les dameons démarrés"); essayez {timeunit.milliseconds.sleep (500);} catch (InterruptedException e) {e.printStackTrace ();}}}Le résultat de sortie final est:
Tous les dameons ont commencé
Thread [Thread-3,5, Main] concurrency.daemonfromfactory@56214c1
Thread [Thread-2,5, Main] concurrency.daemonfromfactory@5724147d
Thread [Thread-0,5, Main] concurrency.daemonfromfactory@144fe080
Thread [Thread-1,5, Main] concurrency.daemonfromfactory@104fa29e
Thread [Thread-8,5, Main] concurrency.daemonfromfactory@5b069a7f
Thread [Thread-9,5, Main] concurrency.daemonfromfactory@1a7288d1
Thread [Thread-7,5, Main] concurrency.daemonfromfactory@25144c3e
Thread [Thread-4,5, Main] concurrency.daemonfromfactory@288523d
Thread [Thread-6,5, Main] concurrency.daemonfromfactory@1edae2a8
Thread [Thread-5,5, Main] concurrency.daemonfromfactory@626007aa
Thread [Thread-3,5, Main] concurrency.daemonfromfactory@56214c1
Thread [Thread-2,5, Main] concurrency.daemonfromfactory@5724147d
Thread [Thread-6,5, Main] concurrency.daemonfromfactory@1edae2a8
Thread [Thread-5,5, Main] concurrency.daemonfromfactory@626007aa
Thread [Thread-4,5, Main] concurrency.daemonfromfactory@288523d
Thread [Thread-9,5, Main] concurrency.daemonfromfactory@1a7288d1
Thread [Thread-7,5, Main] concurrency.daemonfromfactory@25144c3e
Thread [Thread-8,5, Main] concurrency.daemonfromfactory@5b069a7f
Thread [Thread-1,5, Main] concurrency.daemonfromfactory@104fa29e
Thread [Thread-0,5, Main] concurrency.daemonfromfactory@144fe080
Thread [Thread-2,5, Main] concurrency.daemonfromfactory@5724147d
Thread [Thread-3,5, Main] concurrency.daemonfromfactory@56214c1
Thread [Thread-6,5, Main] concurrency.daemonfromfactory@1edae2a8
Thread [Thread-1,5, Main] concurrency.daemonfromfactory@104fa29e
Thread [Thread-0,5, Main] concurrency.daemonfromfactory@144fe080
Thread [Thread-7,5, Main] concurrency.daemonfromfactory@25144c3e
Thread [Thread-8,5, Main] concurrency.daemonfromfactory@5b069a7f
Thread [Thread-5,5, Main] concurrency.daemonfromfactory@626007aa
Thread [Thread-9,5, Main] concurrency.daemonfromfactory@1a7288d1
Thread [Thread-4,5, Main] concurrency.daemonfromfactory@288523d
Thread [Thread-2,5, Main] concurrency.daemonfromfactory@5724147d
Thread [Thread-3,5, Main] concurrency.daemonfromfactory@56214c1
Thread [Thread-8,5, Main] concurrency.daemonfromfactory@5b069a7f
Thread [Thread-7,5, Main] concurrency.daemonfromfactory@25144c3e
Thread [Thread-4,5, Main] concurrency.daemonfromfactory@288523d
Thread [Thread-6,5, Main] concurrency.daemonfromfactory@1edae2a8
Thread [Thread-1,5, Main] concurrency.daemonfromfactory@104fa29e
Thread [Thread-0,5, Main] concurrency.daemonfromfactory@144fe080
Thread [Thread-9,5, Main] concurrency.daemonfromfactory@1a7288d1
Thread [Thread-5,5, Main] concurrency.daemonfromfactory@626007aa
Thread [Thread-3,5, Main] concurrency.daemonfromfactory@56214c1
Thread [Thread-2,5, Main] concurrency.daemonfromfactory@5724147d
Thread [Thread-8,5, Main] concurrency.daemonfromfactory@5b069a7f
4. Tout d'abord, vous devez réaliser que si le thread utilisateur sort soudainement, le thread d'arrière-plan mettra fin à sa méthode d'exécution sans exécuter la clause enfin.
/ * Lorsque vous appelez ce programme, vous verrez que la clause enfin ne sera pas exécutée, mais si vous commentez l'appel à setDaemon (), vous verrez que la clause * enfin sera exécutée. * Ce comportement est correct. Même si vous ne voulez pas ce comportement en fonction de la promesse que vous avez finalement donnée devant vous. Mais c'est le cas. Lorsque le dernier thread non-fond se termine, le fil d'arrière-plan s'arrête soudainement. Parce qu'une fois que Main () sera sorti, le JVM fermera immédiatement tous les * threads en arrière-plan. Parce que vous ne pouvez pas fermer les fils d'arrière-plan d'une manière élégante, ce n'est pas une bonne idée. Les exécuteurs non-Backend sont généralement un * meilleur moyen, car toutes les tâches contrôlées par l'exécuteur peuvent être fermées en même temps. * / class Adaemon implémente Runnable {@Override public void run () {System.out.println ("Démarrer Adaemon"); essayez {timeunit.seconds.sleep (1); } catch (InterruptedException e) {System.out.println ("qui sort via InterruptedException"); } enfin {System.out.println ("Cela devrait toujours s'exécuter?"); }}} classe publique DaemonsDontrunfinally {public static void main (String [] args) {thread t = new Thread (new Adaemon ()); t.setDaemon (true); t.start (); }} Les résultats de sortie finaux sont les suivants:
Démarrer Adaemon
Cependant, si la situation devient la situation suivante, les résultats de sortie seront à nouveau différents:
Class Adaemon implémente Runnable {@Override public void run () {System.out.println ("Démarrer Adaemon"); essayez {timeunit.seconds.sleep (1); } catch (InterruptedException e) {System.out.println ("qui sort via InterruptedException"); } enfin {System.out.println ("Cela devrait toujours s'exécuter?"); }}} classe publique DaemonsDontrunfinally {public static void main (String [] args) {thread t = new Thread (new Adaemon ()); t.setDaemon (true); t.start (); essayez {timeunit.seconds.sleep (1); } catch (InterruptedException e) {e.printStackTrace (); }}}Étant donné que le thread principal ne sort pas soudainement, le thread d'arrière-plan obtient le temps d'exécution pendant le thread principal dort, donc le résultat de l'impression final est:
Démarrer Adaemon
Cela devrait toujours fonctionner?
Ce qui précède est tout le contenu de cet article sur l'analyse des instances de discussion de fond en Java, et j'espère que cela sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!