您可以将 system.in 、 system.out 和 system.err 重新映射到 Java 线程吗?
我有一些旧的 C++ 代码,它们使用 stdio 进行输入和输出。该代码还通过分叉生成新进程。它将 stdio 重新映射到每个新进程,以便每个会话获取其各自的数据。
我正在考虑使用 Java 中的线程来创建子进程。但是,当涉及到如何将 System.in
、 System.out
和 System.err
重新映射到子线程时,我陷入了困境关于创作。
如果可能的话,有人可以指出我正确的方向吗?
I have some old C++ code that uses stdio for input and output. The code also spawns new processes via forking. It remaps stdio to each new process so each session gets its respective data.
I am looking at using threads in Java to create child processes. However, I am stuck when it comes to finding out how to remap System.in
, System.out
and System.err
to the child threads on creation.
Could anyone please point me in the right direction if this is possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
简单的答案不是不将代码编写为直接访问 System.out/in/err。相反,将一个
InputStream
和两个OutputStream
传递给对象的构造函数。然后,该对象直接与这些对象一起工作,而不依赖于它们实际映射到的内容。要访问print()
和println()
,您需要将OutputStream
传递给PrintStream
的构造函数代码>.然后,根据您实际想要执行的操作,您可以使用 System.out 或某些
FileOutputStream
调用构造函数。The simple answer is not not write your code as directly accessing System.out/in/err. Instead have an
InputStream
and twoOutputStream
s passed in to your object's constructor. The object then works directly with those objects and does not depend on what they are actually mapped to. To get access toprint()
andprintln()
, you will pass theOutputStream
in to the constructor of aPrintStream
.Then based on what you actually want to do, you can call the constructor with System.out or some a
FileOutputStream
.生成线程与生成进程不同。当您在 java(和 c++)中生成线程时,它与生成器共享相同的内存空间(即它们共享相同的 sdio 流)。如果你想在java中生成一个新的进程,你可以使用Runtime.exec(),然后你必须手动将io传输到新进程中,java不支持跨进程共享io流边界。
spawning a thread is not the same as spawning a process. when you spawn a thread in java (and c++) it shares the same memory space as the spawner (i.e. they share the same sdio streams). if you wanted to spawn a new process in java, you would use Runtime.exec() and then you would have to manually pipe the io into the new process, java does not support sharing io streams across process boundaries.
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 结合使用以避免过度阻塞。
Java doesn't have fork(), but it has ProcessBuilder and Runtime.exec() for starting new processes (objects of the Process class). You can think of it as of fork()/exec() pair, but without the capability to perform something in between like dup2(). This means you can't redirect the child process' stdio, but you can explicitly write something into its stdin and read from its stdout and stderr, using the corresponding Process methods, or, to be precise, the corresponding methods of input/output streams returned by the getInputStream()/getOutputStream()/getErrorStream() methods of the Process class. This can be valid workaround if you want to have processes instead of threads.
If you want to use threads, then they all share the same stdio. You can redirect it, but it would be pointless since the redirection will affect all the threads. You can use some sort of imitation of IPC with threads using custom InputStream/OutputStream implementations, or you may wish to have a look at the PipedInputStream/PipedOutputStream pair. These can actually be used to set up something like an IPC pipe, probably with conjunction with BufferedInputStream/BufferedOutputStream to avoid excessive blocking.
我建议使用单独的进程,或者显式地将 PrintStream 分配给每个线程。
但是,即使每个线程看到 System.out 的相同对象,也可以将对 System.out 的写入转发到每个线程的不同位置。在启动代码中,您将使用自定义 PrintStream 调用 System.setOut(PrintStream)。此 PrintStream 将覆盖所有打印和写入方法。在这些方法中,它将使用 InheritableThreadLocal 查找线程的 PrintStream 并将方法调用转发给它。
I would recommend using separate processes, or else explicitly assigning a PrintStream to each thread.
However, it is possible to forward writes to System.out to different places for each thread, even though each thread sees the same object for System.out. In your startup code, you would call System.setOut(PrintStream) with a custom PrintStream. This PrintStream would override all the print and write methods. In these methods, it would look up the thread's PrintStream with an InheritableThreadLocal and forward the method call to it.