Généralement, lorsque nous exécutons des méthodes dans d'autres classes en Java, qu'ils soient des appels statiques ou dynamiques, ils sont exécutés dans le processus actuel, c'est-à-dire qu'il n'y a qu'une seule instance de machine virtuelle Java. Parfois, nous devons démarrer plusieurs sous-processus Java via le code Java. Bien que cela ait des ressources système, cela rendra le programme plus stable car le programme nouvellement démarré s'exécute dans différents processus de machine virtuelle.
En Java, nous pouvons utiliser deux méthodes pour atteindre cette exigence. Le moyen le plus simple consiste à exécuter Java ClassName via la méthode EXEC dans l'exécution. Si l'exécution est réussie, cette méthode renvoie un objet de processus. Jetons un coup d'œil à un exemple simple ci-dessous.
// test1.java Importation de fichiers java.io. *; Public class test {public static void main (string [] args) {fileoutputStream fout = new fileoutputStream ("c: // test1 .txt"); fout.close () ; System.out.println ("Appelé avec succès!");}} // test_exec.javapublic class test_exec {public static void main (String [] args) {runtime run = runtime.ge truntime (); processus p = run. exec ("java test1");}}Après avoir exécuté le programme via Java test_exec, j'ai constaté qu'il y avait un fichier Test1.txt supplémentaire sur le lecteur C, mais les informations de sortie "appelées réussies!" Par conséquent, on peut conclure que le test a été exécuté avec succès, mais pour une raison quelconque, les informations de sortie du test ne sont pas sorties dans la console de test_exec. Cette raison est également très simple, car le processus d'enfant de Test_Exec est créé à l'aide de l'exécutif.
Si vous souhaitez produire les informations de sortie du processus de l'enfant, vous pouvez obtenir le flux de sortie du processus de l'enfant via GetInputStream dans le processus (sortie dans le processus de l'enfant, entrée dans le processus parent), puis transférer le flux de sortie de l'enfant processus à partir de la sortie de la console du processus parent. Le code d'implémentation spécifique est le suivant:
// test_exec_out.javaimport java.io. *; Public class test_exec_out {public static void main (string [] args) {runtime run = runtime.getRuntime (); processus p = run.exec ("java test1"); tamponDinputStream dans = new BufferedInputStream (P.GetInputStream ()); BufferedReader br = new BufferedReader (new inputStreamReader (in)); String s; while ((s = br.readline ())! = null) System.out.println (s) ;}}
Comme le montre le code ci-dessus, dans test_exec_out.java, les informations de sortie du processus enfant sont lues par ligne, puis la sortie est effectuée sur chaque ligne dans test_exec_out. La discussion ci-dessus est de savoir comment obtenir les informations de sortie du processus de l'enfant. Ensuite, en plus des informations de sortie, il existe également des informations d'entrée. Étant donné que le processus enfant n'a pas sa propre console, les informations d'entrée doivent également être fournies par le processus parent. Nous pouvons fournir des informations d'entrée au processus de l'enfant via la méthode de processus GetOutputStream (c'est-à-dire les informations d'entrée du processus parent au processus enfant, plutôt que des informations d'entrée de la console). Nous pouvons consulter le code suivant:
// test2.java Importation de fichiers java.io. *; Public class test {public static void main (string [] args) {buffereDader br = new buttereDreader (new inputStreamRead er (System.in)); system.out.println ( "Informations saisies par le processus parent:" + br.readline ());}} // test_exec_in.javaimport java.io. *; Classe publique test_exec_in {public static void main (string [] args) {run time run = runtime .getRuntime (); processus p = run.exec ("java test2"); bufferedwriter bw = new BufferedWriter (new OutputStreamWriter (p.getOutputStream ())); bw.write ("output to Child Process Information"); bw. flush (); bw.close (); À partir du code ci-dessus, nous pouvons voir que Test1 obtient les informations envoyées par test_exec_in et les publie. Lorsque vous n'ajoutez pas bw.flash () et bw.close (), les informations n'atteindront pas le processus de l'enfant, ce qui signifie que le processus de l'enfant entre dans un état de blocage, mais comme le processus parent est sorti, le processus de l'enfant sort également . Si vous souhaitez le prouver, vous pouvez ajouter System.in.read () à la fin, puis afficher le processus Java via le gestionnaire de tâches (sous Windows), et vous constaterez que si vous ajoutez BW.Flush () et BW .Close (), un seul processus Java existe, s'ils sont supprimés, deux processus Java existent. En effet, si les informations sont transmises à Test2, Test2 sort après avoir obtenu les informations. Voici une chose à expliquer que l'exécution de l'exec est asynchrone et n'arrêtera pas d'exécuter le code suivant car un certain programme exécuté est bloqué. Par conséquent, après l'exécution de Test2, le code suivant peut toujours être exécuté.
La méthode Exec a été rechargée plusieurs fois. Ce qui est utilisé ci-dessus n'est qu'une surcharge de celui-ci. Il peut également séparer les commandes et les paramètres, tels que Exec ("java.test2") peut être écrit en tant qu'EXEC ("java", "test2"). EXEC peut également exécuter des machines virtuelles Java avec différentes configurations via des variables d'environnement spécifiées.
En plus d'utiliser la méthode EXEC de Runtime pour créer un processus enfant, vous pouvez également créer un processus enfant via ProcessBuilder. L'utilisation de ProcessBuilder est la suivante:
// test_exec_out.javaimport java.io. *; Classe publique test_exec_out {public static void main (string [] args) {processBuilder pb = new ProcessBui lder ("java", "test1"); process p = pb.start () ;En établissant des processus enfants, ProcessBuilder est similaire à l'exécution. Après avoir obtenu le processus, leurs opérations sont exactement les mêmes.
Comme l'exécution, ProcessBuilder peut également définir les informations de l'environnement, le répertoire de travail, etc. du fichier exécutable. L'exemple suivant décrit comment définir ces informations à l'aide de ProcessBuilder.
ProcessBuilder pb = new ProcessBuilder ("Command", "arg2", "arg2", ''); // définir la carte de variable d'environnement <String, String> Env = pb.environment (); env.put ("key1", : :::::::::::::::::::::::::::::::::::- : :::::::::::::::::::::::::::::::::::- ::::::::::::::::::::::::::::::::: "Value1"); Env.Remove ("key2"); env.put ("key2", env. .get ("key1") + "_test"); pb.Directory ("../ ABCD"); Problème de blocage des processus
Les processus représentés par le processus ne fonctionnent parfois pas sur certaines plates-formes, en particulier lorsqu'ils fonctionnent sur des flux d'entrée standard, des flux de sortie et des sorties d'erreur représentant des processus.
Si l'instruction dans l'exemple ci-dessus qui relie les informations de la sortie standard est modifiée pour lire à partir du flux de sortie d'erreur:
stdout = new BufferedReader (new inputStreamReader (p.getErrorStream ()));
Ensuite, le programme bloquera et ne peut pas être exécuté, mais accrochez-vous.
Lorsque le processus démarre, le flux de sortie standard et le flux de sortie d'erreur sont activés pour préparer la sortie, et lorsque le processus se termine, ils sont fermés. Dans l'exemple ci-dessus, le flux de sortie d'erreur n'a pas de données à sortir et le flux de sortie standard a une sortie de données. Étant donné que les données du flux de sortie standard ne sont pas lues, le processus ne se terminera pas et le flux de sortie d'erreur ne sera pas fermé. Pour résoudre ce problème, vous pouvez d'abord lire le flux de sortie standard, puis lire le mauvais flux de sortie en fonction de l'ordre réel de la sortie.
Cependant, dans de nombreux cas, la séquence de sortie ne peut pas être clairement connue, surtout lorsque des entrées standard sont nécessaires, la situation sera plus compliquée. À l'heure actuelle, les threads peuvent être utilisés pour traiter la sortie standard, la sortie d'erreur et les entrées standard séparément, et le flux ou les données peut être lu en fonction de leur relation de logique métier.
Pour les problèmes causés par les flux de sortie standard et les flux de sortie erronés, vous pouvez utiliser la méthode RedireCterRorstream () de ProcessBuilder pour les combiner en un.
Lorsque vous utilisez la méthode WaitFor () de Process dans un programme, en particulier lors de l'appel de la méthode WaitFor () avant de lire, cela peut également provoquer un blocage. Vous pouvez utiliser des méthodes de thread pour résoudre ce problème, ou vous pouvez appeler la méthode WaitFor () après avoir lu les données pour attendre que le programme se termine.
En bref, je présente ici l'utilisation de la classe ProcessBuilder, en utilisant la méthode RedireCterRorstream pour combiner le flux de sortie standard et le flux de sortie d'erreur en un. , puis appelez la méthode waitfor () pour attendre que le processus se termine.
comme:
Importer Java.io.BufferedReader; {try {list <String> list = new ArrayList <string> (); Add ("Cmd.exe"); )); (line = stdout.readline ())! = null) {System.out.println (ligne);} int ret = p.waitfor (); stdou t .close ();} catch (exception e) {e.printStackTrace ();