【问题标题】:Run external program concurrently and communicate with it through stdin / stdout并发运行外部程序并通过stdin/stdout与之通信
【发布时间】:2011-08-01 06:20:04
【问题描述】:

我希望能够与我的 Java 代码同时运行一个外部程序,即我想启动该程序,然后将控制权返回给调用方法,同时保持外部程序运行。然后,Java 代码将继续生成输入并将其发送到外部程序并接收回输出。

我不想继续加载外部程序,因为它的开销非常大。实现这一目标的最佳方法是什么?谢谢!

【问题讨论】:

  • 你描述的是Runtime.exec()(和`ProcessBuilder)的默认行为。阅读this great article on common stumbling blocks (and their solutions)
  • larson:我真的,真的,建议不要在流媒体上制作任何东西:stackoverflow.com/questions/4674179 否则你将进入一个充满伤害和痛苦的世界。我在这里创建的外部进程可能比 anyone 更多(即:在 lot 用户系统上发布的应用程序上并不断创建外部进程)所以我知道一点点我在说什么。我使用临时文件进行进程通信(网络存在问题,例如触发 AV 通知,这可能会让您的用户吓坏,并且试图从 Java 操作标准输入/输出是妄想)。

标签: java


【解决方案1】:

看看ProcessBuilder。设置 ProcessBuilder 并执行 start 后,您将拥有 Process 的句柄,您可以向其提供输入和读取输出。

这是一个帮助您入门的 sn-p:

ProcessBuilder pb = new ProcessBuilder("/bin/bash");
Process proc = pb.start();

// Start reading from the program
final Scanner in = new Scanner(proc.getInputStream());
new Thread() {
    public void run() {
        while (in.hasNextLine())
            System.out.println(in.nextLine());
    }
}.start();

// Write a few commands to the program.
PrintWriter out = new PrintWriter(proc.getOutputStream());
out.println("touch hello1");
out.flush();

out.println("touch hello2");
out.flush();

out.println("ls -la hel*");
out.flush();

out.close();

输出:

-rw-r--r-- 1 aioobe aioobe 0 2011-04-08 08:29 hello1
-rw-r--r-- 1 aioobe aioobe 0 2011-04-08 08:29 hello2

【讨论】:

  • 我试过了,但由于我的外部程序等待标准输入,它会阻塞,所以我无法从调用方法中获得控制权。我需要控制权,因为外部程序的输入是稍后生成的。
  • 这可能是来自外部程序的读取阻塞。你需要把它放在一个单独的线程中,除非你确切地知道什么时候读。
  • 谢谢!你的答案正是我想要的。
【解决方案2】:

您可以使用 Runtime.getRuntime().exec(...) 启动外部应用程序

要将数据发送到外部程序,您可以在 Processes 输出流上发送数据(您从 exec 中获取一个 Process 对象),或者您可以打开套接字并以这种方式进行通信。

【讨论】:

    【解决方案3】:

    我认为您会发现 java.lang.Process 类的 Javadoc 很有帮助。值得注意的是,您可以从 Process 获取输入和输出流,以便在它运行时与之通信。

    【讨论】:

      【解决方案4】:

      我支持使用ProcessBuilder 的答案。如果您想了解有关此的更多详细信息,以及为什么您应该更喜欢它而不是 Runtime.exec(),请参阅此 entry in the Java glossary。它还展示了如何使用线程与外部进程进行通信。

      【讨论】:

        【解决方案5】:

        由于阻塞,我在尝试通过 stdin/stdout 与外部进程进行双向通信时遇到问题。最后我找到了a github gist,它让我简单优雅地解决了这个问题;该要点实际上基于stackoverflow answer

        查看示例代码的其他答案,但该想法的核心是设置一个用于读取和写入的事件循环(while 循环,睡眠时间为 10 毫秒),并使用低级流操作,以便没有缓存和阻塞继续——只有当你知道其他进程实际上写了一些东西时才尝试阅读(通过InputStream.available())。

        这导致了一种有点奇怪的编程风格,但代码比使用线程要简单得多,而且做得很好。

        【讨论】:

          猜你喜欢
          • 2018-09-24
          • 1970-01-01
          • 1970-01-01
          • 2014-02-14
          • 1970-01-01
          • 2017-02-01
          • 1970-01-01
          • 2019-06-18
          • 2011-06-22
          相关资源
          最近更新 更多