为什么父进程不处理标准输入输出子进程会挂起(Java)?

来源:互联网 发布:创建视图的sql语句代码 编辑:程序博客网 时间:2024/05/01 18:09

最近写Java的多进程程序时遇到一个奇怪的问题,发现程序运行一段时间以后会自动挂起。按道理来说子进程和父进程之间是没有太大的关系的,父进程只是用于开启一个新的子进程,之后就没怎么联系了。最后查到了stackoverflow上面的一片帖子,写的不错。http://stackoverflow.com/questions/16983372/why-does-process-hang-if-the-parent-does-not-consume-stdout-stderr-in-java

Java doesn’t do anything in this area. It just uses OS services to create the pipes.

All Unix like OSs and Windows behave the same in this regard: A pipe with a 4K is created between parent and child. When that pipe is full (because one side isn’t reading), the writing process blocks.

This is the standard since the inception of pipes. There is not much Java can do.

What you can argue is that the process API in Java is clumsy and doesn’t have good defaults like simply connecting child streams to the same stdin/stdout as the parent unless the developer overrides them with something specific.

I think there are two reasons for the current API. First of all, the Java developers (i.e. the guys at Sun/Oracle) know exactly how the process API works and what you need to do. They know so much that it didn’t occur to them that the API could be confusing.

The second reason is that there is no good default that will work for the majority. You can’t really connect stdin of the parent and the child; if you type something on the console, to which process should the input go?

Similarly, if you connect stdout, the output will go somewhere. If you have a web app, there might be no console or the output might go somewhere where no one will expect it.

You can’t even throw an exception when the pipe is full since that can happen during the normal operation as well.

总结一下就是这个问题可能跟Java关系不大,应该是操作系统对pipe处理的问题。因为父子进程之间通信可以利用匿名管道,但是如果子进程往管道里面的数据“塞”满了,父进程却“迟迟”不取,那么操作系统就会hang子进程,不让它接着写数据了。所以这时候子进程就会没反应了。挂起了嘛。

原因找到了,解决这个问题就很简单了,直接开启一个线程不停地去读取匿名管道里面的数据即可。

String javaHome = System.getProperty("java.home");String javaBin = javaHome + File.separator + "bin" + File.separator + "java";String classpath = System.getProperty("java.class.path");String className = klass.getCanonicalName();ProcessBuilder builder = new ProcessBuilder(javaBin, "-cp", classpath, className, String.valueOf(mode));builder.redirectErrorStream(true);process = builder.start();//      process.waitFor();InputStream myIS = process.getInputStream();new Thread(){    public void run() {        if(process == null)            return ;        InputStream is = process.getInputStream();        InputStreamReader isr = new InputStreamReader(is);        BufferedReader br = new BufferedReader(isr);        String line;        try {            while ((line = br.readLine()) != null) {                System.out.println(line);            }        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        System.out.println("Game closed!");    }  }.start();
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 坐火车很累怎么办 坐火车时间太长怎么办 高铁乘务员短发怎么办 来不及买欧洲通票怎么办 拼音输入法不显示汉字怎么办 书法落款写错怎么办 辐射4鼠标延迟怎么办 闭门器卡住了怎么办 货物运输少了一部分怎么办 高铁不能托运怎么办 卖玉营业员新手怎么办 老婆想吐怎么办呀 菜盆下水慢怎么办 下水管道有异味怎么办 厨房下水道地面漏水怎么办 戒指冲到下水道怎么办 农村盖房超出面积怎么办 研究生论文一个盲审没过怎么办 病毒麻疹很痒怎么办 毕业后学校改名怎么办 改名字以后档案怎么办 孩子改名后社保怎么办 改名后支付宝怎么办 毕业改名后学籍怎么办 改名字本科证怎么办 名字改了毕业证怎么办 改年龄后毕业证怎么办 被两家单位录取了怎么办 大专挂科太多怎么办 本科退学后档案怎么办 二本法学生怎么办 高中被开除学籍怎么办 九江学院借读证怎么办 粉末冶金粉加不满怎么办 学校屏蔽移动信号怎么办 铂涛高校代理怎么办 三校生高考没考上怎么办 国家助学金不发怎么办 学校不发助学金怎么办 大专学分修不够怎么办 小孩淋雨感冒了怎么办