【原创】java中的父进程子进程 —— 坑爹的java Runtime.getRuntime().exec
2015-02-13 00:28
701 查看
最近有一个需求,需要用一个java进程启动多个子进程来完成并发任务。由于必须给用户完成任务的反馈,所以需要父进程记录子进程的生命周期。
exec方法返回一个Process对象,在当前进程内调用该对象的waitFor方法,然后父进程就会在该方法阻塞,那么只有在该Process结束的情况下,才会从waitFor中返回。
我写了两个类来测试:
一个是Father类:
hell.jar由子类son导出,具体代码如下:
可是,可是!
明明应该很快结束,结果整整卡了15分有余。。
后来上网查了,才发现这是个坑
文档中如此写道:
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了一个解决办法,具体代码如下:
然后就成功了。
感想:
bat真丑,windows上java的坑真多
exec方法返回一个Process对象,在当前进程内调用该对象的waitFor方法,然后父进程就会在该方法阻塞,那么只有在该Process结束的情况下,才会从waitFor中返回。
我写了两个类来测试:
一个是Father类:
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); } }
可是,可是!
明明应该很快结束,结果整整卡了15分有余。。
后来上网查了,才发现这是个坑
文档中如此写道:
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的坑真多
相关文章推荐
- java中如何获取Runtime.getRuntime().exec()或ProcessBuilder.start()产生的进程信息
- java.lang.Runtime.getRuntime().exec 调用后,等待被调用程序结束后再继续执行
- java Runtime.getRuntime().exec 调用系统脚本/命令注意事项
- Java Runtime.getRuntime.exec() 与linux shell find
- java Runtime.getRuntime().exec 调用系统脚本/命令注意事项
- Eclipse下使用Runtime.getRuntime().exec启动java程序的问题
- Applet虽签名,但是Runtime.getRuntime().exec(cmd)异常:java.security.AccessControlException: access deni
- Java Process中waitFor()的问题(使用Runtime.getRuntime().exec(...)时)
- 如何在JAVA代码中执行 exec master..xp_cmdshell @cmd // 当作SQL语句调用就成了 或者调用 Runtime.getRuntime().exec
- [Android] ProcessBuilder与Runtime.getRuntime().exec分别创建进程的区别
- Eclipse下使用Runtime.getRuntime().exec启动java程序的问题
- Java Runtime.getRuntime().exec()详解
- Runtime.getRuntime().exec(cmd)使用不当引起的java.io.IOException: Too many open files
- Android ProcessBuilder与Runtime.getRuntime().exec诀别创建进程的区别
- java调用命令行Runtime.getRuntime().exec()函数碰到的阻塞问题
- java Runtime.getRuntime().exec()
- 关于java Runtime.getRunTime.exec(String command)的使用
- Java执行Runtime.getRuntime().exec()
- Java Runtime.getRuntime().exec() 执行带空格命令
- 整理java Runtime.getRuntime().exec | 命令