你能将system.in,system.out和system.err重新映射到Java线程吗?

时间:2011-02-13 16:19:25

标签: java multithreading fork stdio

我有一些旧的C ++代码,它使用stdio进行输入和输出。该代码还通过分叉生成新进程。它将stdio重新映射到每个新进程,以便每个会话获取其各自的数据。

我正在寻找使用Java中的线程来创建子进程。但是,在找到如何在创建时将System.inSystem.outSystem.err重新映射到子线程时,我很困惑。

如果有可能,有人可以指出我正确的方向吗?

4 个答案:

答案 0 :(得分:1)

简单的答案不是将您的代码编写为直接访问System.out / in / err。而是将InputStream和两个OutputStream传递给对象的构造函数。然后,对象直接与这些对象一起工作,而不依赖于它们实际映射到的对象。要访问print()println(),您需要将OutputStream传递给PrintStream的构造函数。

然后根据你真正想做的事情,你可以用System.out或一些FileOutputStream来调用构造函数。

答案 1 :(得分:1)

产生一个线程与产生一个进程不同。当你在java(和c ++)中生成一个线程时,它与spawner共享相同的内存空间(即它们共享相同的sdio流)。如果你想在java中生成一个新的进程,你会使用Runtime.exec(),然后你必须手动将io传递给新进程,java不支持跨进程共享io流边界。

答案 2 :(得分:0)

Java没有fork(),但它有ProcessBuilder和Runtime.exec()来启动新进程(Process类的对象)。您可以将其视为fork()/ exec()对,但没有能力执行像dup2()之类的操作。这意味着您不能重定向子进程'stdio,但是您可以使用相应的Process方法显式地将某些内容写入其stdin并从其stdout和stderr读取,或者,确切地说,输入/输出流的相应方法由Process类的getInputStream()/ getOutputStream()/ getErrorStream()方法返回。如果您想要进程而不是线程,这可以是有效的解决方法。

如果你想使用线程,那么它们都共享相同的stdio。您可以重定向它,但这将毫无意义,因为重定向将影响所有线程。您可以使用自定义InputStream / OutputStream实现对线程使用某种模仿IPC,或者您可能希望查看PipedInputStream / PipedOutputStream对。这些实际上可以用来设置类似IPC管道的东西,可能与BufferedInputStream / BufferedOutputStream结合使用,以避免过度阻塞。

答案 3 :(得分:0)

我建议使用单独的进程,或者明确地为每个线程分配一个PrintStream。

但是,即使每个线程看到System.out的相同对象,也可以将对System.out的写入转发到每个线程的不同位置。在您的启动代码中,您将使用自定义PrintStream调用System.setOut(PrintStream)。此PrintStream将覆盖所有打印和写入方法。在这些方法中,它将使用InheritableThreadLocal查找线程的PrintStream,并将方法调用转发给它。