2010-11-12 65 views
3

我有一個程序(使用Java),需要在執行過程中多次使用另一個程序,使用不同的參數。它是多線程的,除了在執行過程中調用該程序外,還需要做其他事情,所以我需要使用Java來完成此任務。在Java中多次運行命令行程序 - 這是正確的嗎?

問題是,所有的Runtime.exec()調用似乎都是由Java以同步的方式完成的,這樣線程就不會受到函數本身的瓶頸,而是在Java調用中遇到瓶頸。因此,我們有一個非常緩慢的運行程序,但這並不是任何系統資源的瓶頸。

爲了解決這個問題,我決定使用這個腳本不關閉進程,並撥打所有電話:

#!/bin/bash 

read choice 
while [ "$choice" != "end" ] 
do 
    $choice 
    read choice 
done 

而且以前所有的exec調用受此取代:

private Process ntpProc; 

Initializer(){ 
    try { 
     ntpProc = Runtime.getRuntime().exec("./runscript.sh"); 
    } catch (Exception ex) { 
     //Error Processing 
    } 
} 

public String callFunction(String function) throws Exception e{ 
    OutputStream os = ntpProc.getOutputStream(); 
    String result = ""; 
    os.write((function + "\n").getBytes()); 
    os.flush(); 
    BufferedReader bis = new BufferedReader(new InputStreamReader(ntpProc.getInputStream())); 
    int timeout = 5; 
    while(!bis.ready() && timeout > 0){ 
     try{ 
     sleep(1000); 
     timeout--; 
     } 
     catch (InterruptedException e) {} 
    } 
    if(bis.ready()){ 
     while(bis.ready()) result += bis.readLine() + "\n"; 
     String errorStream = ""; 
     BufferedReader bes = new BufferedReader(new InputStreamReader(ntpProc.getErrorStream())); 
     while(bes.ready()) errorStream += bes.readLine() + "\n"; 
    } 
    return result; 
} 

public void Destroyer() throws exception{ 
    BufferedOutputStream os = (BufferedOutputStream) ntpProc.getOutputStream(); 
    os.write(("end\n").getBytes()); 
    os.close(); 
    ntpProc.destroy(); 
} 

工作得很好,實際上設法將我的節目表現提高了10倍。所以,我的問題是:這是正確的嗎?還是我錯過了這樣做的事情,最終會使一切都變得非常糟糕?

+0

您是否正確使用Java線程?我的意思是,你打電話給start()還是run()? – 2010-11-12 16:44:08

回答

3

如果要從流程中讀取錯誤和輸入流(又名stderr和stdout),則需要在專用線程上執行此項工作。

主要問題是您需要在緩衝區填滿時清空緩衝區,並且您只能在單獨的線程上執行此操作。

你做了什麼,你已經設法縮短輸出,所以它不會溢出這些緩衝區,但潛在的問題仍然存在。另外,從過去的經驗來看,從Java調用外部進程非常緩慢,所以你的方法可能會更好。

1

只要你不調用Proccess.waitFor(),進程的執行就不會阻塞。正如亞歷克斯所說 - 在你的情況下阻止由這些循環讀取輸出。

您可以使用commons-EXEC包,因爲它提供了正在運行的進程(同步或異步),處理輸出,設置超時的一個很好的方式,等

這裏是一個項目鏈接: http://commons.apache.org/exec/

使用API​​的最好的例子是測試類他們有: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java?view=markup