Tout d'abord, parlons des connaissances conceptuelles liées aux applications et aux processus en Java, puis expliquons comment créer des threads et comment créer des processus. Voici le plan du répertoire de cet article:
1.Concepts liés aux applications et aux processus en Java
2. Comment créer des threads en Java
3.Comment créer un processus en Java
1.Concepts liés aux applications et aux processus en Java
Dans Java, une application correspond à une instance JVM (également appelée processus JVM), et le nom par défaut Java.exe ou Javaw.exe (peut être visualisé via le gestionnaire de tâches sous Windows). Java adopte un modèle de programmation unique, c'est-à-dire que si nous ne créons pas activement des threads dans notre propre programme, nous ne créerons qu'un seul thread, qui est généralement appelé le thread principal. Mais sachez que bien qu'il n'y ait qu'un seul fil pour effectuer des tâches ne signifie pas qu'il n'y a qu'un seul fil dans le JVM. Lors de la création d'une instance JVM, de nombreux autres threads seront créés (tels que les threads de collecteur de déchets).
Étant donné que Java adopte un modèle de programmation unique, lors de l'interface utilisateur de programmation, vous devez prêter attention à la mise en place d'opérations longues dans le thread de l'enfant pour éviter de bloquer le thread principal (lors de la programmation de l'interface utilisateur, le thread principal est le thread d'interface utilisateur, qui est utilisé pour gérer les événements d'interaction utilisateur).
2. Comment créer des threads en Java
Si vous souhaitez créer un fil en Java, il y a généralement deux façons: 1) Hériter de la classe de threads; 2) Implémentez l'interface Runnable.
1. Hériter de la classe de threads
Si vous héritez de la classe de threads, vous devez remplacer la méthode d'exécution et définir les tâches qui doivent être exécutées dans la méthode d'exécution.
class Mythread étend Thread {private static int num = 0; public mythread () {num ++; } @Override public void run () {System.out.println ("activement créé" + num + "threads"); }}Après avoir créé votre propre classe de thread, vous pouvez créer un objet de thread, puis démarrer le thread via la méthode start (). Notez qu'il n'est pas appelé la méthode run () pour démarrer le thread. La méthode d'exécution définit uniquement les tâches qui doivent être exécutées. Si la méthode d'exécution est appelée, elle équivaut à exécuter la méthode d'exécution dans le thread principal, qui n'est pas différente des appels de méthode ordinaire. À l'heure actuelle, un nouveau fil ne sera pas créé pour exécuter les tâches définies.
Classe publique Test {public static void main (String [] args) {mythread thread = new mythread (); thread.start (); }} class Mythread étend Thread {private static int num = 0; public mythread () {num ++; } @Override public void run () {System.out.println ("activement créé" + num + "threads"); }}Dans le code ci-dessus, en appelant la méthode start (), un nouveau thread sera créé. Afin de distinguer la différence entre les appels de méthode start () et les appels de méthode exécutés, veuillez consulter l'exemple suivant:
Classe publique Test {public static void main (String [] args) {System.out.println ("ID de thread principal:" + thread.currentThread (). getID ()); Mythread thread1 = new mythread ("thread1"); thread1.start (); Mythread thread2 = new mythread ("thread2"); thread2.run (); }} class Mythread étend Thread {private String Name; public mythread (String name) {this.name = name; } @Override public void run () {System.out.println ("name:" + name + "Child Thread ID:" + thread.currentThread (). GetID ()); }}Résultats en cours:
À partir des résultats de sortie, les conclusions suivantes peuvent être tirées:
1) Les ID de thread de Thread1 et Thread2 sont différents, et Thread2 et l'ID de thread principal sont les mêmes, ce qui signifie que l'appel de méthode d'exécution ne créera pas un nouveau thread, mais exécutera directement la méthode d'exécution dans le thread principal, qui n'est pas différent des appels de méthode ordinaires;
2) Bien que l'appel de la méthode de démarrage de Thread1 soit appelé avant la méthode d'exécution de Thread2, les informations sur l'appel de méthode d'exécution de Thread2 sont d'abord la sortie, indiquant que le processus de création d'un nouveau thread ne bloquera pas l'exécution ultérieure du thread principal.
2. Implémentez l'interface runnable
En plus de hériter de la classe de threads, la création de threads en Java peut également implémenter des fonctions similaires en implémentant l'interface Runnable. L'implémentation de l'interface Runnable doit remplacer sa méthode d'exécution.
Voici un exemple:
Classe publique Test {public static void main (String [] args) {System.out.println ("ID de thread principal:" + thread.currentThread (). getID ()); Myrunnable runnable = new myrunnable (); Thread thread = nouveau thread (runnable); thread.start (); }} class MyRunnable implémente Runnable {public myrunnable () {} @Override public void run () {System.out.println ("Sous-thread id:" + thread.currentThread (). GetId ()); }}Runnable signifie «tâche» en chinois. Comme son nom l'indique, en implémentant l'interface Runnable, nous définissons une sous-tâche, puis remettons la sous-tâche pour exécuter. Notez que cette méthode doit utiliser Runnable comme paramètre dans la classe de thread, puis créer un nouveau thread pour exécuter la sous-tâche via la méthode de démarrage du thread. Si la méthode d'exécution de Runnable est appelée, un nouveau thread ne sera pas créé et il n'y a pas de différence entre cet appel de méthode ordinaire.
En fait, si vous regardez le code source d'implémentation de la classe de threads, vous constaterez que la classe de threads implémente l'interface Runnable.
Dans Java, ces deux méthodes peuvent être utilisées pour créer des threads pour exécuter des sous-tâches. La méthode spécifique à choisir dépend de vos besoins. Si vous héritez directement de la classe de threads, il peut sembler plus concis que d'implémenter l'interface Runnable. Cependant, comme Java n'autorise que l'héritage unique, si une classe personnalisée doit hériter d'autres classes, vous ne pouvez choisir qu'implémenter l'interface Runnable.
3.Comment créer un processus en Java
En Java, il existe deux façons de créer des processus, impliquant un total de 5 classes principales.
La première méthode consiste à créer un processus via la méthode runtime.exec (), et la deuxième méthode consiste à créer un processus via la méthode de démarrage de ProcessBuilder. Parlons des différences et des liens entre ces deux méthodes.
La première chose dont je veux parler est la classe de processus. La classe de processus est une classe abstraite. Il y a principalement plusieurs méthodes abstraites. Vous pouvez l'apprendre en regardant le code source de la classe de processus:
Situé dans le chemin java.lang.process:
Classe publique Test {public static void main (String [] args) {System.out.println ("ID de thread principal:" + thread.currentThread (). getID ()); Myrunnable runnable = new myrunnable (); Thread thread = nouveau thread (runnable); thread.start (); }} class MyRunnable implémente Runnable {public myrunnable () {} @Override public void run () {System.out.println ("Sous-thread id:" + thread.currentThread (). GetId ()); }}1) Créer un processus via ProcessBuilder
ProcessBuilder est une classe finale qui a deux constructeurs:
public final class processBuilder {private list <string> commande; répertoire de fichiers privé; Carte privée <String, String> Environnement; Boolean redirectorRorstream privé; public processBuilder (list <string> Command) {if (command == null) lancez new nullpointerException (); this.command = commande; } public processBuilder (String ... Command) {this.command = new ArrayList <string> (Command.length); for (String arg: Command) this.command.add (arg); } ......}Le constructeur transmet des paramètres de commande du processus qui doit être créé. Le premier constructeur place les paramètres de commande dans la liste et les transmet sous la forme d'une chaîne indéfiniment longue.
Continuons donc à regarder en bas. Comme mentionné précédemment, nous créons un nouveau processus via la méthode de démarrage de ProcessBuilder. Jetons un coup d'œil à ce qui est fait exactement dans la méthode de démarrage. Ce qui suit est le code source d'implémentation spécifique de la méthode de démarrage:
Le processus public start () lève ioException {// doit convertir en berbe d'abord - une liste malicieuse utilisée par l'utilisateur peut essayer de circuitvent le chèque de sécurité.string [] cmdArray = Command.toArray (nouvelle chaîne [Command.size ()]); For (String Arg: cmdarray) if (arg == null) lance la nouvelle nullpointerException (); // est videstring prog = cmdArray [0]; SecurityManager Security = System.getSecurityManager (); if (Security! = Null) security.checKexec (prog); String dir = répertoire == null? null: répertoire.tostring (); Essayez {return processImpl.Start (cmdArray, Environment, Dir, RedireCterRorstream);} Catch (ioException e) {// Il nous est beaucoup plus facile de créer un message d'erreur de haute qualité // que le code C de bas niveau qui a trouvé le problème. Jetez une nouvelle ioException ("Impossible d'exécuter le programme /" "+ prog +" / "" + (dir == null? "": "(dans Directory /" "+ dir +" / ")") + ":" + e.getMessage (), e);}}Cette méthode renvoie un objet de processus. La première partie de la méthode équivaut à définir certains paramètres en fonction des paramètres de commande et du répertoire de travail SET. La chose la plus importante est une phrase dans le bloc d'essai:
return processImpl.Start (cmdArray, Environment, Dir, RedireCterRorstream);
C'est la phrase qui crée vraiment le processus. Notez que la méthode de démarrage de la classe ProcessImpl est appelée. Ici, nous pouvons savoir que le démarrage doit être une méthode statique. Alors, quel genre de processus est? Cette classe est également située dans le chemin java.lang.processimplml. Jetons un coup d'œil à la mise en œuvre spécifique de cette classe:
ProcessImpl est également une classe finale, qui hérite de la classe de processus:
Classe finale ProcessImpl étend le processus {// Portion dépendant du système de processBuilder.Start () Process static start (String cmdArray [], java.util.map <string, string> Environment, String dir, boolean redirectorRorReMmentBlock (Environment); String envlock = processEnvironment.toenvironmentblock (Environment); Return new ProcessImpl (cmdArray, Envlock, Dir, RedireRerRorRorstream); } ....}Il s'agit de l'implémentation spécifique de la méthode de démarrage de la classe ProcessImpl. En fait, cette phrase est utilisée pour créer un objet ProcessImpl:
Return new ProcessImpl (cmdArray, Envlock, Dir, RedireRerRorRorstream);
Dans ProcessImpl, plusieurs méthodes abstraites de la classe de processus sont implémentées dans la mise en œuvre concrète.
En fait, un objet ProcessImpl est créé via la méthode de démarrage de ProcessBuilder.
Jetons un coup d'œil à l'exemple de l'utilisation de ProcessBuilder pour créer un processus. Par exemple, si je souhaite démarrer un processus via ProcessBuilder pour ouvrir CMD et obtenir des informations d'adresse IP, je peux l'écrire comme ceci:
Classe publique Test {public static void main (String [] args) lève ioException {processBuilder pb = new ProcessBuilder ("cmd", "/ c", "ipconfig / all"); Processus process = pb.start (); Scanner Scanner = nouveau scanner (process.getInputStream ()); while (scanner.hasnextline ()) {System.out.println (Scanner.NextLine ()); } Scanner.Close (); }}La première étape est la plus critique, qui consiste à passer la chaîne de commande au constructeur ProcessBuilder. D'une manière générale, chaque commande indépendante de la chaîne est utilisée comme paramètre distinct, mais il peut également être placé dans la liste dans l'ordre et transmis.
Quant à de nombreux autres usages spécifiques, je ne les élaborerai pas ici, tels que la définition des variables d'environnement de processus et les répertoires de travail via la méthode d'environnement de ProcessBuilder et le répertoire (répertoire de fichiers). Les amis intéressés peuvent consulter les documents API pertinents.
2) Créez un processus via la méthode Exec de Runtime
Tout d'abord, jetons un coup d'œil à l'implémentation spécifique de la classe d'exécution et de la méthode EXEC. L'exécution, comme son nom l'indique, signifie l'exécution, représente l'instance de machine virtuelle où se trouve le processus actuel.
Étant donné que tout processus ne s'exécutera que dans une seule instance de machine virtuelle, un mode singleton est utilisé dans l'exécution, c'est-à-dire qu'une seule instance de machine virtuelle sera générée:
classe publique runtime {private static runtime currentRuntime = new runtime (); / ** * Renvoie l'objet d'exécution associé à l'application Java actuelle. * La plupart des méthodes de classe <code> Runtime </code> sont des méthodes d'instance * et doivent être invoquées par rapport à l'objet d'exécution actuel. * * @return l'objet <code> Runtime </code> associé à l'application Java actuelle *. * / public static runtime getRuntime () {return currentRuntime; } / ** Ne laissez personne instancier cette classe * / private runtime () {} ...}De là, nous pouvons voir que puisque le constructeur de la classe d'exécution est privé, nous ne pouvons obtenir que l'instance d'exécution via GetRuntime. Ensuite, examinons de plus près l'implémentation de la méthode exec. Il existe plusieurs implémentations de surcharge différentes d'EXEC dans l'exécution, mais la fin de l'exécution est cette version de la méthode Exec:
public Process exec (String [] cmdArray, String [] envp, file dir) lève ioException {return new ProcessBuilder (cmdArray) .environment (envp) .directory (dir) .start (); }On peut constater qu'en fait, si le processus est créé via l'exécutif de la classe d'exécution, il est finalement créé via la méthode de démarrage de la classe ProcessBuilder.
Jetons un coup d'œil à un exemple pour voir comment créer un processus via l'exécutif de l'exécution, ou l'exemple précédent, appelez CMD pour obtenir des informations d'adresse IP:
Classe publique Test {public static void main (String [] args) lève ioException {String cmd = "cmd" + "/ c" + "ipconfig / all"; Processus process = runtime.getRuntime (). Exec (cmd); Scanner Scanner = nouveau scanner (process.getInputStream ()); while (scanner.hasnextline ()) {System.out.println (Scanner.NextLine ()); } Scanner.Close (); }}Il convient de noter que la méthode EXEC ne prend pas en charge les paramètres de longueur indéfinie (ProcessBuilder prend en charge les paramètres de longueur indéfinie), donc les paramètres de commande doivent être épissés avant de les passer.
Je vais parler de la façon de créer des fils et des processus en Java pour le moment. Les amis intéressés peuvent se référer aux informations pertinentes.