最近有一个需求,需要用一个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中的父进程子进程 —— 坑爹的java Runtime.getRuntime().exec的更多相关文章

  1. JAVA命令运行cmd命令得到的结果乱码Runtime.getRuntime().exec("");

    Process process = Runtime.getRuntime().exec("cmd /c dir c:"); BufferedReader bufferedReade ...

  2. Java中如何创建进程(转)

    在Java中,可以通过两种方式来创建进程,总共涉及到5个主要的类. 第一种方式是通过Runtime.exec()方法来创建一个进程,第二种方法是通过ProcessBuilder的start方法来创建进 ...

  3. 使用Runtime.getRuntime().exec()在java中调用python脚本

    举例有一个Python脚本叫test.py,现在想要在Java里调用这个脚本.假定这个test.py里面使用了拓展的包,使得pythoninterpreter之类内嵌的编译器无法使用,那么只能采用ja ...

  4. Runtime.getRuntime().exec中命令含有括号问题

    在写批量运行bat工具的时候.想起了之前写的定时小工具里面的运行方法. 使用Runtime.getRuntime().exec方法. Runtime.getRuntime().exec("c ...

  5. [转]java调用外部程序Runtime.getRuntime().exec

    Runtime.getRuntime().exec()方法主要用于执行外部的程序或命令. Runtime.getRuntime().exec共有六个重载方法: public Process exec( ...

  6. JAVA调用可执行程序或系统命令Runtime.getRuntime().exec

    用Java编写应用时,有时需要在程序中调用另一个现成的可执行程序或系统命令,这时可以通过组合使用Java提供的Runtime类和Process类的方法实现.下面是一种比较典型的程序模式: Proces ...

  7. Java Runtime.getRuntime().exec() 执行带空格命令

    可执行文件路径如果包含空格,则在java中不能被获取到. 此时Debug一下,会发现 project=null. project.waitFor 的返回值为1.但是去源路径单击bat文件是可以正常运行 ...

  8. Runtime.getRuntime().exec()实现Java调用python程序

    使用Runtime.getRuntime().exec()来实现Java调用python,调用代码如下所示: import java.io.BufferedReader; import java.io ...

  9. linuxbash 父进程 子进程

    linux登陆linux,就获得一个bash,之后你的bash就是一个独立的进程,被称为pid的就是,之后你在bash下面执行的任何命令都是由这个bash所衍生的,那些被执行的命令被称为子进程.子进程 ...

随机推荐

  1. phprpc 使用实例(同时有Java、Android和Delphi客户端的例子)

    PHPRPC 是一个轻型的.安全的.跨网际的.跨语言的.跨平台的.跨环境的.跨域的.支持复杂对象传输的.支持引用参数传递的.支持内容输出重定向的.支持分级错误处理的.支持会话的.面向服务的高性能远程过 ...

  2. Android资源文件及文件夹介绍

    在Android项目文件夹里面,主要的资源文件是放在res文件夹里面的 1:assets文件夹是存放不进行编译加工的原生文件,即该文件夹里面的文件不会像xml,java文件被预编译,可以存放一些图片, ...

  3. OCA读书笔记(16) - 执行数据库恢复

    16. Performing Database Recovery 确定执行恢复的必要性访问不同接口(EM以及命令行)描述和使用可用选项,如RMAN和Data Recovery Advisor执行恢复- ...

  4. 【剑指offer】q34:丑数

    题目要求第n个丑数.所以对于中间结果不须要保存. def Humble(index): curHum = 1 M2 = 2; M3 = 3; M5 = 5 while index > 1: cu ...

  5. LINUX专题之操作系统字符集

    原创作品,出自 "深蓝的blog" 博客,欢迎转载.转载时请务必注明下面出处,否则追究版权法律责任. 深蓝的blog: http://blog.csdn.net/huangyanl ...

  6. Linux中进行挂起(待机)的命令说明

    /*********************************************************************  * Author  : Samson  * Date   ...

  7. hdu1243(最长公共子序列变形)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1243 分析:dp[i][j]表示前i个子弹去炸前j个恐怖分子得到的最大分.其实就是最长公共子序列加每个 ...

  8. hdu3415(单调队列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3415 题意:一个长度为n包含正负整数的数环,即第1个的左边是第n个.从中选一个不超过k的序列,使得序列 ...

  9. Replace - with an en dash character (–, –) ?

    这个安卓开发过程中eclipse的提示,新浪网友给出这个解决方法:http://blog.sina.com.cn/s/blog_5ea8670101015dgk.html  太笨了. 看看stacko ...

  10. 自己动手写了第三阶段的处理器——教学OpenMIPS处理器蓝图

    我们会继续上传新书<自己动手写处理器>(未公布).今天是第十条.我每星期试试4 从本章開始将一步一步地实现教学版OpenMIPS处理器.本章给出了教学版OpenMIPS的系统蓝图,首先介绍 ...