2014-12-07 58 views
0

我想发送一些字符串到子进程和它们,并且这会以大写字母返回。这个想法是我把一个空字符串,这两个过程将停止。 第一次工作都很棒,但下一次这个过程第二次卡住了,我需要强行关闭。JAVA - 将数据发送到循环中的子进程

父亲代码 - >

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(); 
    } 
} 

}

+1

**为什么**会招致启动多个JVM而不是在另一个中调用另一个方法的开销? – 2014-12-07 21:39:20

+0

而你并不需要空行。只要关闭输出流,就会在子进程的输入流中产生流结束。你不需要别的东西。 – EJP 2014-12-07 23:04:39

回答

0

您在这里有几个问题。

  • 首先,在你的主循环(父亲和儿子)中,你没有检查文件结束。这意味着您可以从流式阅读器获取null,并且当您尝试访问isEmpty()时,您将获得NullPointerException

  • 其次,您从未将空行传递给儿子进程,因为只要您从escritorPadre.readLine()获得的行为空,就会跳出while循环。所以儿子检查isEmpty()是徒劳的。最好在你退出时关闭流向儿子的溪流(无论如何,你总是必须关闭河流),然后在儿子身边处理儿子。

  • 但最重要的是:你从儿子阅读的循环总是会卡住,因为你只会在儿子端得到null。如果儿子在其输出流上使用close()(或儿子终止),则只会得到流结束。但是如果你在儿子身上使用close(),你将无法再次写入标准输出。

    所以你的循环只是一直在等待儿子写别的东西,而儿子在写东西之前正在等待父亲写下别的东西。所以这个过程陷入了僵局。

您可以决定儿子应该发送一些特殊的输出(空行),以便知道何时停止读取其输出。

但是,你有一个标准错误的问题。从儿子的输出结束阅读后,您开始阅读标准错误。因此,为了让您离开该循环,在每次写入输出后,还必须在标准错误处打印空行,并且还要向每个catch正在打印的堆栈轨迹添加一条空行。然后,你还必须在父亲的循环中添加一个空行检查来阅读儿子的标准错误。

个人而言,我认为这不是很优雅。但它是可行的。

无论如何,为了让你开始,在父亲身边,你应该确保你关闭所有的流,并在阅读时检查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(); 
} 

而且在儿子还,一定要关闭所有的资源或使用try-与资源,并检查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(); 
}