일반적으로 Java의 다른 클래스에서 정적 또는 동적 호출에 관계없이 현재 프로세스에서 실행됩니다. 즉, Java Virtual Machine 인스턴스가 하나만 실행됩니다. 때로는 Java 코드를 통해 여러 Java 하위 프로세스를 시작해야합니다. 이 작업을 수행하면 일부 시스템 리소스가 필요하지만 새로 시작된 프로그램은 한 프로세스에서 예외가 발생하면 다른 하위 프로세스에 영향을 미치지 않기 때문에 프로그램이 더 안정적입니다.
Java에서는이 요구 사항을 달성하기 위해 두 가지 방법을 사용할 수 있습니다. 가장 쉬운 방법은 런타임의 EXEC 메소드를 통해 Java ClassName을 실행하는 것입니다. 실행이 성공하면이 메소드는 프로세스 객체를 반환하면 IOException 오류가 발생합니다. 아래의 간단한 예를 살펴 보겠습니다.
// test1.java 파일 import java.io.*; public class test {public static void main (String [] args) {fileoutputStream fout = new FileOutputStream ( "C : // test1 .txt"); fout.close () ; system.out.println ( "성공적으로!");}} // test_exec.javapublic class test_exec {public static void main (string [] args) {runtime run = runtime.ge truntime (); process p = run. exec ( "java test1");}}Java Test_Exec을 통해 프로그램을 실행 한 후 C 드라이브에 추가 테스트 1.txt 파일이 있음을 알았지 만 출력 정보는 콘솔에 나타나지 않았습니다. 따라서 테스트가 성공적으로 실행되었다고 결론 지을 수 있지만 어떤 이유로 든 테스트의 출력 정보는 Test_Exec의 콘솔에서 출력되지 않습니다. Test_Exec의 아동 프로세스에는 EXEC를 사용하여 생성되기 때문에 이러한 이유는 매우 간단합니다.
아동 프로세스의 출력 정보를 출력하려면 GetInputStream의 프로세스 (아동 프로세스의 출력, 부모 프로세스의 입력)를 통해 아동 프로세스의 출력 스트림을 얻은 다음 아동의 출력 스트림을 전송할 수 있습니다. 부모 프로세스의 콘솔 출력에서 프로세스. 특정 구현 코드는 다음과 같습니다.
// test_exec_out.javaimport java.io.*; public class test_exec_out {public static void main (string [] args) {runtime run = runtime.getRuntime (); process p = run.exec ( "java test1"); BufferedInputStream = new bufferedInputStream (p.getInputStream ()); bufferedReader br = new bufferedReader (new inputStreamReader (in)); String S; while ((s = br.readline ())! = null) system.out.println (s) ;}}
위의 코드에서 볼 수 있듯이 Test_Exec_out.java에서 자식 프로세스의 출력 정보는 행으로 읽은 다음 Test_Exec_out의 각 줄에서 출력이 수행됩니다. 위의 논의는 아동 프로세스의 출력 정보를 얻는 방법입니다. 그런 다음 출력 정보 외에도 입력 정보도 있습니다. 아동 프로세스에는 자체 콘솔이 없으므로 입력 정보는 부모 프로세스에서도 제공해야합니다. GetoutPutStream 프로세스 방법 (즉, 콘솔에서 정보를 입력하지 않고 부모 프로세스에서 아동 프로세스에 대한 입력 정보)을 통해 아동 프로세스에 입력 정보를 제공 할 수 있습니다. 다음 코드를 볼 수 있습니다.
// test2.java 파일 import java.io.*; public class test {public static void main (string [] args) {bufferedReader br = new bufferedReader (new inputStreamRead ER (System.In)); System.out.println ( "부모 프로세스에서 입력 한 정보 :" + br.readline ());}} // test_exec_in.javaimport java.io. .getRuntime (); process p = run.exec ( "java test2"); bufferedWriter bw = new bufferedWriter (new outputStreamWriter (p.getoutPutStream ())); bw.write ( "어린이 프로세스 정보로 출력"); BW. flush (); bw.close (); 위의 코드에서 Test1은 Test_Exec_in에 의해 전송 된 정보를 가져 와서 출력한다는 것을 알 수 있습니다. bw.flash () 및 bw.close ()를 추가하지 않으면 정보가 아동 프로세스에 도달하지 않으므로 아동 프로세스가 차단 상태로 들어가지만 부모 프로세스가 종료되면 자녀 프로세스도 종료합니다. . 이를 증명하려면 끝에 System.in.read ()를 추가 한 다음 작업 관리자 (Windows 아래)를 통해 Java 프로세스를 볼 수 있으며 Bw.flush () 및 BW를 추가하면 확인할 수 있습니다. .Close (), 하나의 Java 프로세스만이 존재하며, 제거되면 두 개의 Java 프로세스가 존재합니다. 정보가 Test2로 전달되면 정보를 얻은 후 Test2가 종료되기 때문입니다. 다음은 EXEC의 실행이 비동기식이며 실행되는 특정 프로그램이 차단되므로 다음 코드 실행을 중단하지 않을 것이라고 설명해야 할 사항이 있습니다. 따라서 Test2를 실행 한 후에도 다음 코드를 여전히 실행할 수 있습니다.
exec 메소드가 여러 번 다시로드되었습니다. 위에서 사용되는 것은 단지 과부하 일뿐입니다. 또한 exec ( "java.test2")와 같은 명령과 매개 변수를 분리 할 수 있습니다 ( "java", "test2"). Exec는 지정된 환경 변수를 통해 다른 구성으로 Java 가상 머신을 실행할 수 있습니다.
Runtime의 Exec 방법을 사용하여 자식 프로세스를 구축하는 것 외에도 ProcessBuilder를 통해 하위 프로세스를 구축 할 수도 있습니다. ProcessBuilder의 사용은 다음과 같습니다.
// test_exec_out.javaimport java.io.*; public class test_exec_out {public static void main (string [] args) {processBuilder pb = new ProcessBui Lder ( "java", "test1"); process p = pb.start () ;………}}아동 프로세스를 설정할 때 프로세스 빌더는 런타임과 유사합니다. 프로세스를 얻은 후에는 운영이 정확히 동일합니다.
런타임과 마찬가지로 ProcessBuilder는 실행 파일의 환경 정보, 작업 디렉토리 등을 설정할 수도 있습니다. 다음 예는 ProcessBuilder를 사용 하여이 정보를 설정하는 방법을 설명합니다.
ProcessBuilder PB = New ProcessBuilder ( "명령", "Arg2", "Arg2", '' '); // 환경 변수 맵 설정 <문자열, String> Env = pb.environment (); env.put ( "key1", : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : "value1");env.remove("key2");env.put("key2", env .get ( "key1") + "_test"); pb.directory ( "../ abcd"); 프로세스 차단 문제
프로세스로 표시되는 프로세스는 때때로 일부 플랫폼에서 잘 작동하지 않습니다. 특히 프로세스를 나타내는 표준 입력 스트림, 출력 스트림 및 오류 출력에서는 프로세스가 차단 될 수 있습니다.
위의 예에서 표준 출력의 정보를 다시 읽는 명령문이 오류 출력 스트림에서 읽을 수 있도록 수정 된 경우 :
stdout = new bufferedReader (new inputStreamReader (p.geterRorstream ()));
그러면 프로그램이 차단되어 실행할 수 없지만 거기에 매달려 있습니다.
프로세스가 시작되면 표준 출력 스트림과 오류 출력 스트림이 켜져 출력을 준비하고 프로세스가 끝나면 닫힙니다. 위의 예에서, 오류 출력 스트림에는 출력 할 데이터가없고 표준 출력 스트림에는 데이터 출력이 있습니다. 표준 출력 스트림의 데이터는 읽지 않으므로 프로세스가 끝나지 않으며 오류 출력 스트림이 닫히지 않으므로 전체 프로그램이 차단됩니다. 이 문제를 해결하기 위해 먼저 표준 출력 스트림을 읽은 다음 출력의 실제 순서에 따라 잘못된 출력 스트림을 읽을 수 있습니다.
그러나, 많은 경우에, 출력 시퀀스는 명확하게 알 수 없으며, 특히 표준 입력이 필요한 경우 상황이 더 복잡해집니다. 현재 스레드를 사용하여 표준 출력, 오류 출력 및 표준 입력을 별도로 처리 할 수 있으며 스트림 또는 데이터는 비즈니스 로직 관계에 따라 읽을 수 있습니다.
표준 출력 스트림과 잘못된 출력 스트림으로 인한 문제의 경우 ProcessBuilder의 RedirecterRorstream () 메소드를 사용하여 현재 표준 출력 데이터를 읽을 수 있습니다.
프로그램에서 Process 's Waitfor () 메소드를 사용하는 경우, 특히 읽기 전에 Waitfor () 메소드를 호출 할 때도 막힘이 발생할 수 있습니다. 스레드 메소드를 사용 하여이 문제를 해결하거나 데이터를 읽고 프로그램이 종료 될 때까지 기다린 후 Waitfor () 메소드를 호출 할 수 있습니다.
요컨대, 나는 표준 출력 스트림과 오류 출력 스트림을 하나로 결합한 redirecterrorstream 메소드를 사용하여 ProcessBuilder 클래스의 사용을 소개합니다. 그런 다음 Waitfor () 메소드를 호출하여 프로세스가 종료 될 때까지 기다립니다.
좋다:
import java.io.inputStreamReader; {list <string> new arraylist <string> () process process p = null; add는 "cmd.exe") ( "/c"; ); ((line = stdout.readline ()! = null) {system.out.println (line)} int ret = p.waitfor (); stdou t .close ()} catch (E.PrintstackTrace)};