2008-12-04 66 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來查找要委派的目標的實現。線程本地人通常是邪惡的,但在不幸的情況下可能有用。

從澄清,似乎原來的海報沒有必要創建一個單獨的過程。

相關問題