Maison  >  Article  >  Java  >  Introduction détaillée aux threads démons et aux threads utilisateur en Java

Introduction détaillée aux threads démons et aux threads utilisateur en Java

黄舟
黄舟original
2017-09-30 09:47:261732parcourir

Cet article présente principalement le thread démon et le thread utilisateur en Java. L'éditeur pense que c'est plutôt bon. Maintenant, je vais le partager avec vous et le donner comme référence. Suivons l'éditeur pour y jeter un œil

Les threads Java sont divisés en deux catégories : le thread démon (thread démon) et le thread utilisateur (thread utilisateur). Au démarrage de la JVM, la fonction principale sera appelée, et le thread utilisateur. thread où se trouve la fonction principale C'est un thread utilisateur. C'est le thread que nous pouvons voir. En fait, de nombreux threads démons sont également démarrés à l'intérieur de la JVM, comme les threads de garbage collection. Alors, quelle est la différence entre les threads démons et les threads utilisateur ? L'une des différences est que lorsque le dernier thread non-démon se termine, la JVM se terminera normalement, qu'il existe ou non un thread démon, ce qui signifie que la fin du thread démon n'affecte pas la sortie de la JVM. L'implication est que tant qu'un thread utilisateur n'est pas terminé, la JVM ne se fermera pas dans des circonstances normales.

Alors comment créer un thread démon en Java ? Le code est le suivant :


public static void main(String[] args) {

    Thread daemonThread = new Thread(new Runnable() {
      public void run() {
        
      }
    });
    
    //设置为守护线程
    daemonThread.setDaemon(true);
    daemonThread.start();
    
  }

On voit qu'il suffit de définir le paramètre démon du thread sur true.

Ce qui suit est un exemple pour approfondir la compréhension de la différence entre les threads utilisateur et les threads démon. Regardez d'abord le code suivant :


public static void main(String[] args) {

    Thread thread = new Thread(new Runnable() {
      public void run() {
        for(;;){}
      }
    });
    
    //启动子线
    thread.start();
    
    System.out.print("main thread is over");
  }

. Le résultat est :


Le code ci-dessus crée un thread de thread dans le thread principal. Il y a une boucle infinie dans le thread de thread à partir des résultats de l'exécution. le code, on peut voir que le thread principal a fini de s'exécuter, puis la JVM continue. Vous avez déjà quitté ? Le carré rouge sur le côté droit de la sortie de l'EDI indique que le processus JVM ne s'est pas terminé. De plus,
l'exécution de ps -eaf | grep java sur mac affichera les résultats, ce qui peut également prouver cette conclusion.

Ce résultat montre que lorsque le thread parent se termine, le thread enfant peut toujours exister, c'est-à-dire que le cycle de vie du thread enfant n'est pas affecté par le thread parent. Cela montre également que le processus JVM ne se terminera pas lorsque le thread utilisateur existe toujours. Ensuite, définissons le fil de discussion ci-dessus comme thread démon et exécutons-le pour voir quel sera l'effet :


    //设置为守护线程
    thread.setDaemon(true);
    //启动子线
    thread.start();

Le résultat de l'exécution est :

Comme ci-dessus, définissez le thread comme thread démon avant de démarrer le thread. À partir du résultat de sortie, nous pouvons voir que le processus JVM a été terminé. Vous ne pouvez même plus voir le processus JVM. si vous exécutez ps -eaf |grep java. Dans cet exemple, la fonction principale est le seul thread utilisateur et le thread de thread est un thread démon. Lorsque le thread principal termine son exécution, la JVM constate qu'il n'y a plus de threads utilisateur et mettra fin au processus JVM.

En Java, une fois le thread principal terminé, la JVM démarrera automatiquement un thread appelé DestroyJavaVM. Ce thread attendra la fin de tous les threads utilisateur, puis mettra fin au processus JVM. prouvez cette conclusion :

Ouvrez le code JVM, et finalement la fonction c JavaMain sera appelée


int JNICALL
JavaMain(void * _args)
{  
  ...
  //执行Java中的main函数 
  (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
  
  //main函数返回值
  ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
  
  //等待所有非守护线程结束,然后销毁JVM进程
  LEAVE();
}

LEAVE est une définition de macro dans le c langage, défini comme suit :


#define LEAVE() \
  do { \
    if ((*vm)->DetachCurrentThread(vm) != JNI_OK) { \
      JLI_ReportErrorMessage(JVM_ERROR2); \
      ret = 1; \
    } \
    if (JNI_TRUE) { \
      (*vm)->DestroyJavaVM(vm); \
      return ret; \
    } \
  } while (JNI_FALSE)

La fonction de la macro ci-dessus est en fait de créer un thread nommé DestroyJavaVM pour attendre la fin de tous les threads utilisateur.

Résumé : Si vous souhaitez que le processus JVM se termine immédiatement après la fin du thread principal, vous pouvez définir le thread comme thread démon lors de la création du thread. Sinon, si vous souhaitez que le thread enfant continue de fonctionner après le. Le thread principal se termine, attendez que le thread enfant se termine. Après avoir laissé le processus JVM se terminer, définissez le thread enfant comme thread utilisateur. Le framework open source Tomcat utilise des threads démons et des threads utilisateur pour s'exécuter conjointement. la publication du livre Concurrent Package Source Code Analysis on the Basics of Java Concurrent Programming.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn