【原創】java中的父進程子進程 —— 坑爹的java Runtime.getRuntime().exec

最近有一個需求,須要用一個java進程啓動多個子進程來完成併發任務。因爲必須給用戶完成任務的反饋,因此須要父進程記錄子進程的生命週期。java

exec方法返回一個Process對象,在當前進程內調用該對象的waitFor方法,而後父進程就會在該方法阻塞,那麼只有在該Process結束的狀況下,纔會從waitFor中返回。windows

 

我寫了兩個類來測試:併發

一個是Father類:ide

public class Father {
	private static int count = 0;
	private static int total = 3;
	private static String target = "./hell.jar";
	private static List<Process> child = new ArrayList<Process> ();
	
	public static void main (String[] args) {
		Runtime run = Runtime.getRuntime();
		System.out.println("wait..");
		for (int i = 0; i < total; i ++) {
			try {
				Process num = run.exec("java -jar " + target);
				child.add(num);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		for (Process item : child) {
			try {
				item.waitFor();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("All work finished!");
	}
}

  

hell.jar由子類son導出,具體代碼以下:測試

public class Son {	
	public static void main (String[] args) {
		for (int i = 0; i < 10000; i ++) {
			System.out.println(i);
		}
		System.exit(0);

	}
}

  

但是,但是!orm

明明應該很快結束,結果整整卡了15分有餘。。對象

 

後來上網查了,才發現這是個坑blog

文檔中如此寫道:生命週期

Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock. 進程

 

這意思簡單歸納爲:緩衝區若是滿了,爺就掛起來

 

換言之,子進程把寫往stdout的緩衝區佔滿了,因此子進程掛起了,因而父進程就要消逝在永久的等待中了。

 

瞭解了緣由,解決辦法就簡單了:消耗掉輸出。

個人辦法是重定向。

 

可是對exec重定向彷佛也有坑。。Goolge了一個解決辦法,具體代碼以下:

public class Father {
	private static int count = 0;
	private static int total = 3;
	private static String target = "./hell.jar";
	private static List<Process> child = new ArrayList<Process> ();
	
	public static void main (String[] args) {
		Runtime run = Runtime.getRuntime();
		System.out.println("wait..");
		for (int i = 0; i < total; i ++) {
			try {
				Process num = run.exec("cmd /c java -jar " + target + " 1>>1.txt 2>&1"); // 把stdout和stderr的輸出重定向到1.txt中
				child.add(num);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		for (Process item : child) {
			try {
				item.waitFor();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		System.out.println("All work finished!");
	}
}

  

而後就成功了。

 

感想:

bat真醜,windows上java的坑真多

相關文章
相關標籤/搜索