2008-12-04 36 views
1

假设实例xCallable<T>,如何在单独的进程中运行x以便我可以重定向进程的标准输入和输出?例如,有没有办法从Callable建立Process?是否有标准的Executor可以控制输入和输出?Java:在单独的进程中运行一个Callable

[更新]这不是重要的是,Callable在执行一个新的进程,而不是一个新的线程。我想要的是将Callable实例放在一个“线束”中,这样​​我就可以控制它的标准输入/标准输出。 AFAIK,这需要一个新的过程。

回答

2

更普遍:

给定一个实例x赎回利用全局变量A和B,我怎么能同时运行这样的x即x看到自定义值A和B,而不是“原始”的价值观A和B?

而最好的答案是,不要使用全局变量。依赖注入类似的东西。扩展Callable并添加方法setStdIn,setStdOut(和setStdErr,如果您需要的话)。

我知道这不是您正在寻找的答案,但我所看到的解决方案都需要一个新的过程,并且您将Callable变为新过程的唯一方法是更改​​代码的Callable,所以它是可序列化的,或者提供一个类名或者其他一些破解,所以不要进行会给你一个讨厌,脆弱的解决方案的修改,而只是做正确的*

*“right”被广泛接受的依赖注入模式提供了松耦合。因人而异

UPDATE:为响应评述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)。

0

看一看的ProcessBuilder类,它可以让你捕捉到它启动过程的输出和错误的选项。

您可以创建一个运行的可调用一个主类,然后再启动它作为一个的ProcessBuilder其他JVM。 Main类可以接受你的callable的类名作为命令行输入参数,并使用Class.forName()和Class.newInstance()加载它。

如果您希望它运行特定的可调用实例,另一种方法是在启动其他进程(这将是两个进程之间非常粗略的通信形式)之前将该实例序列化为文件。

的问题是,你为什么要这么做?你不能在另一个线程中运行你的可调用吗? java.util.concurrent有一些有用的线程池,仅供参考。

+0

ProcessBuilder,AFAICT需要命令行字符串而不是Callable。我一定要调用这个实例,而不是根据类名创建一个新的实例。至于进程与线程,请参阅上文。 – 2008-12-04 23:43:26

+0

我的意思是说,您将java.exe作为ProcessBUilder的命令,对于Main类,您提供了一个运行可调用的包装器。当然,您需要序列化实例并将文件名作为参数传递给主类。 或者只是使用System.setIn()/ out()等。 – Yoni 2008-12-06 03:45:36

1

标准输入/标准输出可以重定向整个系统,但我不确定它可以重定向到单个线程 - 你总是从系统中获取它。 (尽管你可以让System.out转到另一个流,但我曾用它来捕获堆栈跟踪,然后才有一种方法将跟踪作为字符串)

您可以重定向stdin/stdout,然后运行可调用重定向它,但是如果其他任何东西在重定向时使用System.out,它也会转到您的新文件。

如果你想去那条路线,方法将是System.setIn()和System.setOut()(和System.setErr())。

1

尽量使用上面的参数化,依赖注入或任何你想调用它的结构来构造你的代码。避免静态,即使那些打扮成单身或隐藏在不好的图书馆中。

如果您不想删除System.in/out/err的使用情况,那么您很幸运。这些可以全局设置为System.set(In/Out/Err)。为了能够为单个线程进行不同的流式传输,请设置一个使用ThreadLocal来查找要委派的目标的实现。线程本地人通常是邪恶的,但在不幸的情况下可能有用。

从澄清,似乎原来的海报没有必要创建一个单独的过程。

相关问题