鉴于x
的实例Callable<T>
,如何在单独的流程中运行x
,以便我可以重定向流程的标准输入和输出?例如,有没有办法从Process
构建Callable
?是否有标准Executor
可以控制输入和输出?
[更新] Callable
在新进程中执行而不是新线程并不重要。我想要的是将Callable
实例放在“harness”中,以便我可以控制它的stdin / stdout。 AFAIK,这需要一个新的过程。
答案 0 :(得分:2)
更一般地说:
给定一个使用全局变量A和B的Callable实例x,如何同时运行x使得x看到A和B的自定义值,而不是A和B的“原始”值?
最好的答案是,不要使用全局变量。依赖注入这样的东西。扩展Callable并添加方法setStdIn,setStdOut(如果需要,还可以添加setStdErr)。
我知道这不是您正在寻找的答案,但我所看到的解决方案都需要一个新的流程,而您将Callable变为新流程的唯一方法是更改代码Callable所以它是可序列化的,或者提供一个类名,或者其他一些hack,所以不要做出会给你一个讨厌,脆弱的解决方案的改变,而是正确行事*
*“正确”是使用广泛接受的依赖注入模式来提供松散耦合。 YMMV
更新:回复评论1.这是您的新界面:
import java.io.InputStream;
import java.io.PrintStream;
import java.util.concurrent.Callable;
public interface MyCallable<V> extends Callable<V> {
void setStdIn(InputStream in);
void setStdOut(PrintStream out);
}
你的任务看起来像是:
import java.io.InputStream;
import java.io.PrintStream;
public class CallableTask implements MyCallable<Object> {
private InputStream in = System.in;
private PrintStream out = System.out;
public void setStdIn(InputStream in) {
this.in = in;
}
public void setStdOut(PrintStream out) {
this.out = out;
}
public Object call() throws Exception {
out.write(in.read());
return null;
}
}
无需进程。任何解决方案(甚至一个使用进程)几乎肯定会以某种方式要求对Callables进行代码更改。这是最简单的(只需用this.out替换System.out)。
答案 1 :(得分:1)
stdin / stdout可以重定向到整个系统,但我不确定它是否可以重定向到单个线程 - 你总是从System获取它。 (你可以让System.out转到另一个流,我已经用它来捕获堆栈跟踪,然后才有一个方法来获取跟踪字符串)
你可以重定向stdin / stdout,运行callable然后重定向它,但是如果在重定向的时候还有其他任何东西使用System.out,那么它也会转到你的新文件。
如果你想走那条路,方法将是System.setIn()和System.setOut()(和System.setErr())。
答案 2 :(得分:1)
努力使用上面的参数化,依赖注入或任何你想要调用的代码来构建代码。避免使用静力学,即使是那些打扮成单身或藏在坏图书馆里的人。
如果您不想删除System.in/out/err
的使用情况,那么您很幸运。这些可以使用System.set(In/Out/Err)
进行全局设置。为了能够针对各个线程进行不同的流式设置,请设置一个使用ThreadLocal
来查找要委派的目标的实现。线程本地通常是邪恶的,但在不幸的情况下可能很有用。
从澄清来看,原始海报似乎无需创建单独的流程。
答案 3 :(得分:0)
看看ProcessBuilder类,它为您提供了捕获它启动的进程的stdout和stderr的选项。
您可以创建一个运行Callable的Main类,然后使用ProcessBuilder将其作为另一个jvm启动。 Main类可以接受您的callable的类名作为命令行输入参数,并使用Class.forName()和Class.newInstance()加载它。
另一种方法是,如果您希望它运行特定的可调用实例,则在启动另一个进程之前将实例序列化为文件(这将是两个进程之间非常粗略的通信形式)。
问题是,你为什么要这样做?你能不能在另一个线程中运行你的callable? java.util.concurrent有一些有用的线程池,仅供参考。