【原创】java中的父进程子进程 —— 坑爹的java Runtime.getRuntime().exec
最近有一个需求,需要用一个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的更多相关文章
- JAVA命令运行cmd命令得到的结果乱码Runtime.getRuntime().exec("");
Process process = Runtime.getRuntime().exec("cmd /c dir c:"); BufferedReader bufferedReade ...
- Java中如何创建进程(转)
在Java中,可以通过两种方式来创建进程,总共涉及到5个主要的类. 第一种方式是通过Runtime.exec()方法来创建一个进程,第二种方法是通过ProcessBuilder的start方法来创建进 ...
- 使用Runtime.getRuntime().exec()在java中调用python脚本
举例有一个Python脚本叫test.py,现在想要在Java里调用这个脚本.假定这个test.py里面使用了拓展的包,使得pythoninterpreter之类内嵌的编译器无法使用,那么只能采用ja ...
- Runtime.getRuntime().exec中命令含有括号问题
在写批量运行bat工具的时候.想起了之前写的定时小工具里面的运行方法. 使用Runtime.getRuntime().exec方法. Runtime.getRuntime().exec("c ...
- [转]java调用外部程序Runtime.getRuntime().exec
Runtime.getRuntime().exec()方法主要用于执行外部的程序或命令. Runtime.getRuntime().exec共有六个重载方法: public Process exec( ...
- JAVA调用可执行程序或系统命令Runtime.getRuntime().exec
用Java编写应用时,有时需要在程序中调用另一个现成的可执行程序或系统命令,这时可以通过组合使用Java提供的Runtime类和Process类的方法实现.下面是一种比较典型的程序模式: Proces ...
- Java Runtime.getRuntime().exec() 执行带空格命令
可执行文件路径如果包含空格,则在java中不能被获取到. 此时Debug一下,会发现 project=null. project.waitFor 的返回值为1.但是去源路径单击bat文件是可以正常运行 ...
- Runtime.getRuntime().exec()实现Java调用python程序
使用Runtime.getRuntime().exec()来实现Java调用python,调用代码如下所示: import java.io.BufferedReader; import java.io ...
- linuxbash 父进程 子进程
linux登陆linux,就获得一个bash,之后你的bash就是一个独立的进程,被称为pid的就是,之后你在bash下面执行的任何命令都是由这个bash所衍生的,那些被执行的命令被称为子进程.子进程 ...
随机推荐
- Android面向HTTP协议发送get请求
/** * 採用get请求的方式 * * @param username * @param password * @return null表示求得的路径有问题,text返回请求得到的数据 */ pub ...
- That's life,多一些韧性,才有更多的任性(转)
如果是正确的选择,就不要遵守太多规则. 若有容纳之心,便丰富了自己,也闪了他人,平常心,平常事 阅读,是保持时尚最节约的方式,也是快乐的源泉.可人生难免失意,有了快乐的能力,还应有面对沮丧的心胸. 相 ...
- ZOJ 1171 Sorting the Photos
1. 题目描述 给你一叠照片,有的正面朝上,有的反面朝上,朝上的用字母U,朝下的用字母D 可以从一个位置开始到最顶端,把这一叠拿出来,反转,然后再放回那一叠照片上面. 试求出最少的翻转次数,使所有的照 ...
- stm32 ARM中的RO、RW和ZI DATA
一直以来对于ARM体系中所描述的RO,RW和ZI数据存在似是而非的理解,这段时间对其仔细了解了一番,发现了一些规律,理解了一些以前书本上有的但是不理解的东西,我想应该有不少人也有和我同样的困惑,因此将 ...
- Javascript新手集中营
javascript是世界上最流行的编程语言,也许没有之一,看看github,stackoverflow上面的开源项目和问答就可略知一二.它可以用来开发web app.服务器.或者联合nati ...
- Android中<meta-data>的使用
在AndroidManifest.xml中.<meta-data>元素能够作为子元素,被包括在<activity>.<application> .<servi ...
- TRIZ系列-创新原理-29-气动或液压结构原理
气动或液压结构原理的详细表述例如以下:1)用气态或液态部件替代固体部件.能够用空气或者水,也能够用气垫或水垫,使这些部件膨胀.这条原理符合系统的动态性进化法则-柔性化.在改造系统时,我们能够尝试将系统 ...
- JMX操作ActiveMQ(1)
我们知道ActiveMQ broker的管理接口是通过JMX方式提供的. 一个简单的访问方式就是通过jconsole,输入 service:jmx:rmi:///jndi/rmi://localhos ...
- hdu1513(最长公共子序列)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 题意:将一个字符串转变为回文串的最少添加字符个数 分析:只要想到将字符串逆序后与原字符串求最长公 ...
- SE 2014年3月31日
一. 描述OSPF划分区域的优势. OSPF划分区域的优势主要表现在以下几个方面: 1. 当网络中路由器的数量增大时,划分区域有利于减轻一部分性能较低的设备的处理和维护LSA数据库. 2. 区域的划分 ...