En general, cuando ejecutamos métodos en otras clases en Java, ya sean llamadas estáticas o dinámicas, se ejecutan en el proceso actual, es decir, solo hay una instancia de máquina virtual Java en ejecución. A veces, necesitamos iniciar múltiples subprocesos Java a través del código Java. Aunque hacer esto ocupa algunos recursos del sistema, hará que el programa sea más estable porque el programa recién iniciado se ejecuta en diferentes procesos de máquina virtual.
En Java podemos usar dos métodos para lograr este requisito. La forma más fácil es ejecutar Java ClassName a través del método EXEC en tiempo de ejecución. Si la ejecución es exitosa, este método devuelve un objeto de proceso. Echemos un vistazo a un simple ejemplo a continuación.
// test1.java File Import java.io.*; Public class test {public static void main (string [] args) {fileOutputStream fout = new FileOutputStream ("c: // test1 .txt"); fout.close () ; System.out.println ("llamado con éxito!");}} // test_exec.javapublic class test_exec {public static void main (string [] args) {runtime run = runtime.ge tuntime (); proceso p = run. exec ("Java test1");}}Después de ejecutar el programa a través de Java Test_Exec, descubrí que había un archivo test1.txt adicional en la unidad C, pero la información de salida "se llama correctamente!" Por lo tanto, se puede concluir que la prueba se ha ejecutado con éxito, pero por alguna razón, la información de salida de la prueba no se produce en la consola de test_exec. Esta razón también es muy simple, porque el proceso infantil de Test_Exec se crea usando Exec.
Si desea obtener la información de salida del proceso infantil, puede obtener la secuencia de salida del proceso infantil a través de getInputStream en proceso (salida en el proceso del niño, entrada en el proceso principal) y luego transferir la secuencia de salida del niño Proceso desde la salida de la consola del proceso principal. El código de implementación específico es el siguiente:
// test_exec_out.javaimport java.io.*; Public class test_exec_out {public static void main (string [] args) {runtime run = runtime.getRuntime (); proceso p = run.exec ("java test1"); bufferedinputStream in in in in in in in in = new BufferedInputStream (p.getInputStream ()); BufferedReader BR = new BufferedReader (new InputStreamReader (in)); String S; while ((s = br.readline ())! = null) system.out.println (s) ;}}
Como se puede ver en el código anterior, en test_exec_out.java, la información de salida del proceso infantil se lee por fila, y luego la salida se realiza en cada línea en test_exec_out. La discusión anterior es cómo obtener la información de salida del proceso infantil. Luego, además de la información de salida, también hay información de entrada. Dado que el proceso infantil no tiene su propia consola, la información de entrada también debe ser proporcionada por el proceso principal. Podemos proporcionar información de entrada al proceso del niño a través del método de proceso GetOutputStream (es decir, información de entrada del proceso principal al proceso del niño, en lugar de la información de entrada de la consola). Podemos ver el siguiente código:
// test2.Java File Import java.io.*; Public class test {public static void main (string [] args) {bufferedReader br = new BufferedReader (new InputStreamread ER (System.in)); System.out.println ( "Información ingresada por el proceso principal:" + br.readline ());}} // test_exec_in.javaimport java.io.*; Public class test_exec_in {public static void main (string [] args) {run tiempo de ejecución = tiempo de ejecución .getRuntime (); proceso p = run.exec ("java test2"); bufferedwriter bw = new BufferedWriter (nuevo OutputStreamWriter (p.getOutputStream ())); BW.Write ("Output to Child Process Information"); BW. FLUSH (); BW.CLOSE (); En el código anterior, podemos ver que Test1 obtiene la información enviada por test_exec_in y la genera. Cuando no agrega bw.flash () y bw.close (), la información no alcanzará el proceso infantil, lo que significa que el proceso infantil ingresa a un estado de bloqueo, pero dado que el proceso principal ha salido, el proceso infantil también sale . Si desea probar esto, puede agregar System.in.Read () al final y luego ver el proceso Java a través del Administrador de tareas (en Windows), y lo encontrará si agrega BW.Flush () y BW .Close (), solo existe un proceso de Java, si se eliminan, existen dos procesos Java. Esto se debe a que, si la información se pasa a Test2, Test2 sale después de obtener la información. Aquí hay una cosa que se explica que la ejecución de Exec es asíncrona y no dejará de ejecutar el siguiente código porque un determinado programa que se ejecuta está bloqueado. Por lo tanto, después de ejecutar Test2, el siguiente código aún se puede ejecutar.
El método EXEC ha sido recargado muchas veces. Lo que se usa anteriormente es solo una sobrecarga de ello. También puede separar comandos y parámetros, como Exec ("java.test2") se puede escribir como ejecutor ("java", "test2"). EXEC también puede ejecutar máquinas virtuales Java con diferentes configuraciones a través de variables de entorno especificadas.
Además de usar el método EXECTime de Runtime para construir un proceso infantil, también puede construir un proceso infantil a través de ProcessBuilder. El uso de ProcessBuilder es el siguiente:
// test_exec_out.javaimport java.io.*; Public class test_exec_out {public static void main (string [] args) {ProcessBuilder pb = new ProcessBui lder ("java", "test1"); proceso p = pb.start () ; ...}}Al establecer procesos infantiles, ProcessBuilder es similar al tiempo de ejecución. Después de obtener el proceso, sus operaciones son exactamente las mismas.
Al igual que el tiempo de ejecución, ProcessBuilder también puede establecer la información del entorno, el directorio de trabajo, etc. del archivo ejecutable. El siguiente ejemplo describe cómo establecer esta información usando ProcessBuilder.
ProcessBuilder pb = new ProcessBuilder ("comando", "arg2", "arg2", '' '); // establecer el mapa variable de entorno <string> env = pb.environment (); env.put ("key1", :::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::::::::: : ::::::::::::::::::::::::::::::::ingD .get ("key1") + "_test"); pb.directory ("../ abcd"); Problema de bloqueo de procesos
Los procesos representados por el proceso a veces no funcionan bien en algunas plataformas, especialmente cuando funcionan en flujos de entrada estándar, flujos de salida y salidas de error que representan procesos.
Si la declaración en el ejemplo anterior que vuelve a leer la información de la salida estándar se modifica para leer desde la secuencia de salida de error:
stDout = new BufferedReader (new InputStreamReader (p.getErrorStream ()));
Entonces el programa bloqueará y no se puede ejecutar, pero cuelga allí.
Cuando se inicia el proceso, la secuencia de salida estándar y la secuencia de salida de error se activan para preparar la salida, y cuando finaliza el proceso, están cerrados. En el ejemplo anterior, la secuencia de salida de error no tiene datos que se emitan, y la transmisión de salida estándar tiene salida de datos. Dado que los datos en la secuencia de salida estándar no se leen, el proceso no finalizará y el flujo de salida de error no se cerrará. Para resolver este problema, primero puede leer la secuencia de salida estándar y luego leer la secuencia de salida incorrecta de acuerdo con el orden real de la salida.
Sin embargo, en muchos casos, la secuencia de salida no se puede conocer claramente, especialmente cuando se requiere la entrada estándar, la situación será más complicada. En este momento, los subprocesos se pueden usar para procesar la salida estándar, la salida de error y la entrada estándar por separado, y la secuencia o los datos se pueden leer de acuerdo con su relación lógica comercial.
Para los problemas causados por las transmisiones de salida estándar y las secuencias de salida erróneas, puede usar el método RedirectterRorRorRorR de ProcessBuilder para combinarlos en este momento, solo lea los datos de salida estándar.
Al usar el método WaitFor () de Process en un programa, especialmente cuando llame al método Waitfor () antes de leer, también puede causar bloqueo. Puede usar métodos de subprocesos para resolver este problema, o puede llamar al método Waitfor () después de leer datos para esperar a que el programa finalice.
En resumen, aquí introduzco el uso de la clase ProcessBuilder, utilizando el método redirectterRorStream para combinar el flujo de salida estándar y la secuencia de salida de error en uno. y luego llame al método Waitfor () para esperar a que termine el proceso.
como:
import java.io.bufferedreader; {intente {list <String> list = new ArrayList <String> (); Agregar ("cmd.exe"); ); ((línea = stdout.readline ())! = null) {system.out.println (línea); stdou t .close ();