Geralmente, quando executamos métodos em outras classes em Java, sejam chamadas estáticas ou dinâmicas, são executadas no processo atual, ou seja, existe apenas uma instância de máquina virtual Java em execução. Às vezes, precisamos iniciar vários subprocessos Java através do código Java. Embora isso faça alguns recursos do sistema, isso tornará o programa mais estável porque o programa recém -iniciado é executado em diferentes processos da máquina virtual.
Em Java, podemos usar dois métodos para atingir esse requisito. A maneira mais fácil é executar o Java ClassName através do método EXEC no tempo de execução. Se a execução for bem -sucedida, esse método retornará um objeto de processo. Vamos dar uma olhada em um exemplo simples abaixo.
// test1.java arquivo importa java.io.*; Public class Test {public static void main (string [] args) {fileOutputStream fout = new FileOutputStream ("c: // test1 .txt"); fout.close () ; EXEC ("Java Test1");}}Depois de executar o programa através do Java Test_Exec, descobri que havia um arquivo Test1.txt adicional na unidade C, mas as informações de saída "chamadas com sucesso!" Portanto, pode -se concluir que o teste foi executado com sucesso, mas, por algum motivo, as informações de saída do teste não são emitidas no console de test_exec. Esse motivo também é muito simples, porque o processo filho de Test_exec é criado usando o EXEC.
Se você deseja gerar as informações de saída do processo filho, poderá obter o fluxo de saída do processo filho através do getInputStream em processo (saída no processo filho, entrada no processo pai) e depois transferir o fluxo de saída da criança processo da saída do console do processo pai. O código de implementação específico é o seguinte:
// test_exec_out.javaimport java.io. = new BufferErDInputStream (p.getInputStream ()); BufferReader Br = new BufferredReader (new InputStreamReader (in)); string s; while ((s = b.readline ())! = null) System.out.println (s) ;}}
Como pode ser visto no código acima, em test_exec_out.java, as informações de saída do processo filho são lidas por linha e, em seguida, a saída é executada em cada linha em test_exec_out. A discussão acima é como obter as informações de saída do processo filho. Então, além das informações de saída, também existem informações de entrada. Como o processo filho não possui seu próprio console, as informações de entrada também devem ser fornecidas pelo processo pai. Podemos fornecer informações de entrada para o processo filho através do método de processo GetOutstream (ou seja, informações de entrada do processo pai para o processo filho, em vez de informações de entrada do console). Podemos olhar para o seguinte código:
// test2.java arquivo import java.io.*; Public class Test {public static void main (string [] args) {bufferredreader br = new buffarredreader (new inputStreamRead er (system.in)); system.out.println ( "Informações inseridas pelo processo pai:" + br.readline ());}} // test_exec_in.javaimport java.io.*; Public class Test_exec_in {public static void main (string [] args) {run run = runtime .getRuntime (); processo p = run.exec ("java test2"); bufferwriter bw = new bufferwriter (new outputStreamWriter (p.getOutputStream ())); bw.Write ("Saída para informações do processo filho"); BW. Flush (); BW.Close (); A partir do código acima, podemos ver que o teste1 recebe as informações enviadas por test_exec_in e a produzir. Quando você não adiciona bw.flash () e bw.close (), as informações não atingirão o processo filho, o que significa que o processo infantil entra em um estado de bloqueio, mas como o processo pai saiu, o processo infantil também sai . Se você quiser provar isso, pode adicionar System.in.read () no final e, em seguida, visualizar o processo Java através do gerenciador de tarefas (no Windows), e você descobrirá que se adicionar BW.flush () e BW .Close (), existe apenas um processo Java, se forem removidos, existem dois processos Java. Isso ocorre porque, se as informações forem passadas para o TEST2, o TEST2 sairá após a obtenção das informações. Aqui está uma coisa a ser explicada que a execução do EXEC é assíncrona e não parará de executar o código a seguir, porque um determinado programa executado está bloqueado. Portanto, após a execução do TEST2, o código a seguir ainda pode ser executado.
O método EXEC foi recarregado muitas vezes. O que é usado acima é apenas uma sobrecarga. Ele também pode separar comandos e parâmetros, como EXEC ("java.test2") pode ser escrito como EXEC ("java", "test2"). O EXEC também pode executar máquinas virtuais Java com diferentes configurações através de variáveis de ambiente especificadas.
Além de usar o método EXEC do Runtime para criar um processo infantil, você também pode criar um processo filho através do ProcessBuilder. O uso do ProcessBuilder é o seguinte:
// test_exec_out.javaimport java.io.*; Public class Test_exec_out {public static void main (String [] args) {Processbuilder pb = new ProcessBui lder ("java", "test1"); processo p = pb.start () ;Ao estabelecer processos filhos, o ProcessBuilder é semelhante ao tempo de execução. Depois de obter o processo, suas operações são exatamente as mesmas.
Como o tempo de execução, o ProcessBuilder também pode definir as informações do ambiente, o diretório de trabalho etc. do arquivo executável. O exemplo a seguir descreve como definir essas informações usando o ProcessBuilder.
ProcessBuilder PB = new ProcessBuilder ("Command", "Arg2", "Arg2", '' '); // Definir mapa variável de ambiente <string, string> Env = pb.environment (); Env.put ("key1", : ::::::::::::::::::::::Here :::::::::::::::::::hee :::::::::::::::::heo the : ::::::::::::::::::::::Here :::::::::::::::::::hee :::::::::::::::::heo the : :::::::::::::::::::::::here ::::::::: "value1"); Env.Remove ("Key2"); Env.put ("Key2", Env .get ("key1") + "_test"); pb.directory ("../ abcd"); Problema de bloqueio de processos
Os processos representados pelo processo às vezes não funcionam bem em algumas plataformas, especialmente ao operar em fluxos de entrada padrão, fluxos de saída e saídas de erro que representam processos.
Se a instrução no exemplo acima que relva as informações da saída padrão for modificada para ler no fluxo de saída de erro:
stdout = new buffarreder (new InputStreamReader (p.getErrorStream ()));
Em seguida, o programa bloqueará e não pode ser executado, mas fique lá.
Quando o processo é iniciado, o fluxo de saída padrão e o fluxo de saída de erro são ativados para preparar a saída e, quando o processo termina, eles são fechados. No exemplo acima, o fluxo de saída de erro não possui dados a serem emitidos e o fluxo de saída padrão possui saída de dados. Como os dados no fluxo de saída padrão não são lidos, o processo não termina e o fluxo de saída de erro não será fechado. Para resolver esse problema, você pode primeiro ler o fluxo de saída padrão e depois ler o fluxo de saída errado de acordo com a ordem real da saída.
No entanto, em muitos casos, a sequência de saída não pode ser claramente conhecida, especialmente quando a entrada padrão é necessária, a situação será mais complicada. No momento, os threads podem ser usados para processar a saída padrão, saída de erro e entrada padrão separadamente, e o fluxo ou os dados podem ser lidos de acordo com o relacionamento lógico de negócios.
Para problemas causados por fluxos de saída padrão e fluxos de saída errôneos, você pode usar o método RedirecterRorStream () do ProcessBuilder para combiná -los em um.
Ao usar o método waitfor () do processo em um programa, especialmente ao chamar o método waitfor () antes de ler, ele também pode causar bloqueio. Você pode usar os métodos de thread para resolver esse problema ou pode ligar para o método waitfor () depois de ler os dados para aguardar o término do programa.
Em resumo, aqui apresento o uso da classe ProcessBuilder, usando o método RedirecterRorStream para combinar o fluxo de saída padrão e o fluxo de saída de erro em um. e depois ligue para o método waitfor () para aguardar o término do processo.
como:
Importar Java.io.BufferReadador de importação; {tente {list <string> list = novo Arraylist <string> (); add ("cmd.exe"); ); (Line = stdout.readline ())! = null) {System.out.println (linha); stdou t .close ();