制作过程等待

时间:2014-03-20 16:55:25

标签: java

我使用以下代码通过命令提示符

运行终端命令
String[] command =
        {
      "zsh"
          };
                Process p = Runtime.getRuntime().exec(command);
                new Thread(new SyncPipe(p.getErrorStream(), b)).start();
                new Thread(new SyncPipe(p.getInputStream(), b)).start();
                PrintWriter stdin = new PrintWriter(p.getOutputStream());
                stdin.println("source ./taxenv/bin/activate");
                stdin.println("python runner.py");
                stdin.close();
                int returnCode = 0;
                try {
                    returnCode = p.waitFor();

                    String path2 = b + "/logs.txt"; // I am getting b value passed in from gc.jsp
                    if(new File(path2).exists())
                    {
                        BufferedReader reader = new BufferedReader(new FileReader(path2));

                            while ((line1 = reader.readLine()) != null) 
                                {
                                    content= content + line1 +"<br>";
                                }
                            reader.close();
                            request.setAttribute("logs", content);

                            RequestDispatcher rd = request.getRequestDispatcher("gc.jsp");
                            rd.forward(request, response);


                }
                }
                catch (InterruptedException e) {
                    e.printStackTrace();

                }
                    System.out.println("Return code = " + returnCode +b);
    }               
    class SyncPipe implements Runnable
    {

    public SyncPipe(InputStream istrm, String c) {
          istrm_ = istrm;
          b_ = c;
      }

    @SuppressWarnings("unused")
    public void run() {
          try
          {
              final byte[] buffer = new byte[1024];
            for(int length = 0; (length = istrm_.read(buffer)) != -1; )
              {
                   str = str + IOUtils.toString(istrm_, "UTF-8") + b_;
              }
            System.out.println(str);

            String location = b_ + "/" + "logs.txt";
            File file = new File(location);
            if(!file.exists())
            {
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(str);
            bw.close();


          }

          catch (Exception e)
          {
              e.printStackTrace();
          }
      }
      private final InputStream istrm_;
      private final String b_;

当我运行此代码时,我希望将其重定向到gc.jsp,但它显示如下

enter image description here

现在,当我刷新上面的页面时,我按预期获得输出,如下所示。

enter image description here

为什么会发生这种情况,我该如何解决?

============================= EDIT ================= =========

我添加了

bw.close() //Closing bufferedwriter
fw.close() //Closing file writer

仍然没有用。

现在,我添加了

TimeUnit.SECONDS.sleep(5);

这适用于小文件,所以基本上问题是来自行

的代码
  

String path2 = b +“/ logs.txt”;

必须等待进程p完成。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

您的问题是您在SyncPipe完成文件写入之前尝试阅读文件。您可以通过等待所有线程完成(join()

来解决此问题
Process p = Runtime.getRuntime().exec(command);
Thread threadError = new Thread(new SyncPipe(p.getErrorStream(), b));
Thread threadInput = new Thread(new SyncPipe(p.getInputStream(), b));

threadError.start();
threadInput.start();

/* writing to process */

// wait until your process finished
p.waitFor();

// wait for both threads until they finished writing to files
threadError.join();
threadInput.join();

// read your files

说明:由于进程p已停止,因此当Input / ErrorStream关闭时,您的SyncPipe线程将停止。然后它会将所有内容写入文件并正确关闭文件。之后,Thread正确停止。

join方法告诉主线程(join的调用者)等待线程停止(加入的被调用者,例如threadError)。 waitFor有点等同于join

之后,您可以确定所有线程都已正确停止(pthreadErrorthreadInput),因此所有文件都写入磁盘。现在你可以阅读它们了。