JAVA-在循环中将数据发送到子进程
我想把一些字符串发送给一个子进程,然后用大写字母返回。我的想法是,我把一个空字符串,这两个进程将停止。 第一次效果很好,但下一次过程在第二次被卡住时,我需要强制关闭 父亲代码->JAVA-在循环中将数据发送到子进程,java,process,inputstream,outputstream,Java,Process,Inputstream,Outputstream,我想把一些字符串发送给一个子进程,然后用大写字母返回。我的想法是,我把一个空字符串,这两个进程将停止。 第一次效果很好,但下一次过程在第二次被卡住时,我需要强制关闭 父亲代码-> public class padre { public static void main(String[] args){ System.out.println("Soy el padre"); try { Process p = Runtime.getRuntime().exec("ja
public class padre {
public static void main(String[] args){
System.out.println("Soy el padre");
try {
Process p = Runtime.getRuntime().exec("java -jar C:\\Users\\Cristian\\Desktop\\hijo.jar");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader escritorPadre = new BufferedReader(isr);
//Leer del hijo
BufferedReader brHijo = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader brHijoError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//EScribir en el hijo
OutputStream os = p.getOutputStream();
String lineaConsola;
while((lineaConsola = escritorPadre.readLine()).isEmpty() == false){
lineaConsola +="\n";
os.write(lineaConsola.getBytes());
os.flush();
String linea;
while((linea = brHijo.readLine()) != null){
System.out.println(linea);
System.out.println("Atascado en el while del padre");
}
while((linea = brHijoError.readLine()) != null){
System.out.println(linea);
System.out.println("Atascado en el while del padre error");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
子代码->
public class hijo {
public static void main(String[] args){
InputStreamReader in = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(in);
String linea;
try {
while(!(linea = br.readLine()).isEmpty()){
System.out.println("Hijo -> " + linea.toUpperCase()+"\n");
System.out.println("Atascado en el while del hijo");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}这里有几个问题 首先,在父循环和子循环中,您并没有检查文件的结尾。这意味着您可以从流读取器获得null,并且当您尝试访问isEmpty时,将获得一个NullPointerException 其次,永远不要将空行传递给子进程,因为一旦从escritorPadre.readLine获得的行为空,就可以退出while循环。因此,儿子检查isEmpty是徒劳的。最好在退出时立即关闭子流,不管怎样,在完成流时始终必须关闭它们,并在子端处理null 但最重要的是:用于读取子循环的循环总是会被卡住,因为您只会从流末尾的子端得到null。并且,只有当子系统在其输出流上使用close或子系统终止时,您才能得到流的末尾。但是,如果在子端使用close,您将无法再次写入标准输出 因此,你的循环一直在等待儿子写其他东西,而儿子则在等待父亲写其他东西之后再写。因此,该过程处于死锁状态 你可以决定儿子应该发送一些特殊的输出,一个空行,这样你就知道什么时候停止读取它的输出 但是你有一个标准误差的问题。读取完子输出后,开始读取标准错误。因此,为了允许您离开该循环,您还必须在每次写入输出后将一个空行打印到标准错误,并向从每个捕获打印的堆栈跟踪中添加一个空行。然后,您还必须在读取子标准错误的父循环中添加空行检查 就我个人而言,我认为这不是很优雅。但这是可行的 无论如何,为了让您开始,在父端,您应该确保关闭所有流,并在读取时检查null。比如:
try {
p = Runtime.getRuntime().exec("java -jar C:\\Users\\Cristian\\Desktop\\hijo.jar");
} catch ( IOException e ) {
e.printStackTrace();
return;
}
// Use try-with-resources to open all the streams and readers
// so that they will be closed automatically
try (
BufferedReader escritorPadre = new BufferedReader(new InputStreamReader(System.in));
//Leer del hijo
BufferedReader brHijo = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader brHijoError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//EScribir en el hijo
OutputStream os = p.getOutputStream();
) {
String lineaConsola;
// Read until either end-of-file or empty line
while((lineaConsola = escritorPadre.readLine()) != null && ! lineaConsola.isEmpty()){
... // I ommitted the reading from the son until you decide how you want to arrange it.
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
在son中,还要确保关闭所有资源或使用try with resources,并检查null和空行:
try (
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
){
while((linea = br.readLine()) != null && ! linea.isEmpty()){
System.out.println("Hijo -> " + linea.toUpperCase()+"\n");
System.out.println("Atascado en el while del hijo");
// Decide how you want to handle telling the father that output is done
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
为什么启动多个JVM而不是在一个JVM中调用另一个方法会产生开销?而且您不需要空行。仅关闭输出流将在子进程的输入流处生成流的结尾。你不需要其他任何东西。