2010-08-27 51 views
1

我有一個批處理過程,可以將WAV順序轉換爲MP3。問題是,在數千人之後,有太多的文件保持打開狀態,並且會在文件上限內運行。如何測試「打開的文件太多」問題

它這樣做的原因是因爲在SystemCommandTasklet代碼:

FutureTask<Integer> systemCommandTask = new FutureTask<Integer>(new Callable<Integer>() { 
    public Integer call() throws Exception { 
     Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory); 
     return process.waitFor(); 
    } 
}); 

這有讓我依賴於JVM清理過程,留下的文件打開,這樣的討厭的副作用。

我已經重寫它是這樣:

FutureTask<Integer> systemCommandTask = new FutureTask<Integer>(new Callable<Integer>() { 
    public Integer call() throws Exception { 
     Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory); 
     int status = process.waitFor(); 

     process.getErrorStream().close(); 

     process.getInputStream().close(); 

     process.getOutputStream().flush(); 
     process.getOutputStream().close(); 

     process.destroy(); 

     return status; 
    } 

}); 

我95%肯定,這個工程在我的Mac(感謝LSOF),但我怎麼做一個適當的測試,將工作在任何系統證明我正在嘗試做的是實際工作?

回答

0

證明將是困難的。但是...

創建一個(虛擬)命令,雖然做得不多但保留了文件的鎖定,就像真實情況一樣。這可以確保您的測試不依賴於實際使用的命令。

創建一個測試,使用舊版本啓動SystemCommandTask,但使用DummyCommand。讓它經常開始任務,直到你得到預期的異常。可以調用所需任務的數量N

更改測試以啓動100xN任務。

將任務更改爲新版本。如果測試變爲綠色,則應合理確定您的代碼正常工作。

+0

我目前的問題是N似乎在我的開發機器上是無限的。 – 2010-08-27 20:47:56

+0

如果您無法在系統上重現問題,則需要一個允許重現運行測試問題的系統。 或者檢查文件是否實際打開,但我猜你的系統上沒有文件打開,這樣也不起作用。 – 2010-08-27 21:50:00

0

您可以嘗試編碼以避免它。

爲什麼你不主動限制一次100的任務數量?

在這種情況下,您可以使用一些池化機制來執行像線程池一樣的工作。

+0

我沒有並行運行,雖然...這只是一個.exec之後。問題是,除非你顯式調用process.destroy,否則你將依賴於JVM來關閉文件。如果你足夠快,你會淹沒操作系統的限制。 – 2010-08-27 19:28:26

+0

然後,您可以嘗試在每次處理後放置幾毫秒的時間(afer process.destroy)。 GC應該被執行。 – YoK 2010-08-27 19:51:22

1
  1. 您不應該使用運行時#exec(),因爲該進程沒有附加到JVM的。請看看j.l.ProcessBuilder,它返回一個由JVM進程控制的進程。因此,傾銷流程可能會迫使系統釋放/關閉資源。
  2. 您應該使用j.u.c.Executors來安排和限制進程。
  3. 您也可以使用「ulimit -Sn」(「ulimit -Hn」由於系統健康狀況而不應該是首選)讀取限制。
  4. 檢查您的工具,轉換您的媒體是否保留完成後資源(泄漏,等待來電信號等)的資源。
+0

但是,我的第一個任務是能夠在任何系統上的命令上重新創建此錯誤。它不會發生在我的Mac上,永遠不會發生。並且更改ulimit或launchctl實際上會導致JVM更快地清理文件句柄!春天批次的人寫了原文,所以我不願意改變它的意思。 – 2010-08-27 20:47:18

+0

此外,ProcessBuilder給我留下了同樣的問題。我如何證明調用Process.destroy完成任何事情? – 2010-08-27 21:31:55

+0

我花了一些時間考慮你的#2建議,但這不能回答我如何正確地重新創建/測試這個問題。 – 2010-08-28 17:10:40