1、系統最近遇到的一個問題,需要處理原始目錄下的文件,而file.list() 方法相當於linux命令中的ls。當文件夾中的文件過多的時候,會直接卡死。卡死的主要原因是:
默認情況下,ls命令會將輸出排序。爲了排序,ls命令先將所有文件的名稱讀入內存。當遇到一個非常大的目錄時,它就在那裏不斷地讀入文件名,並且內存佔用越來越大,直到將所有文件一次性以字母數字順序列出來。
而ls-1 -f命令並不執行排序操作,只是讀取目錄然後立即顯示文件。
所以系統上獲取文件進行了改造。java中直接執行linux命令可以使用Runtime.getRuntime().exec。但process.waitFor()方法可能發生無休止或者接近於無休止的阻塞。
造成 process.waitFor()的主要原因是,Process 需要向主線程彙報運行狀況,緩存區是有限的。一直不清除緩存將導致阻塞。
方法一:需要在發送線程中開兩個子線程:分別清空 InputStream 和 ErrorStream。
方法二:將process.waitFor()放在一個子線程中。在主線程中通過子線程的join方法設置超時時間。如果超過設置的時間,
process.waitFor仍然返回空,就將子線程打斷,並將process.destroy();
系統最終採用第二種方法:
private String[] listPathNew(int count) {
InputStreamReader ir = null;
String[] readFile = new String[0];
String line;
List files = new ArrayList();
try {
log.info("------開始從原始目錄搬運文件");
long startTime = System.currentTimeMillis();
// 調用系統命令解壓文件
String [] cmd={"/bin/sh","-c","ls -l -f|head -"+count};
File ofile = new File(ProComMailMutiply.oldmailbox_path);
Process process = Runtime.getRuntime().exec(cmd, null, ofile);
new ProcessClearStream(process.getInputStream(),"INFO",files).start();
new ProcessClearStream(process.getErrorStream(),"ERROR",files).start();
// 等待進程正常完成
process.waitFor();
readFile = (String[]) files.toArray(new String[files.size()]);
log.info("------搬運文件花費了" + (System.currentTimeMillis() - startTime)
+ " ms");
} catch (Exception e) {
log.error("搬運文件出錯了" + e.toString());
}finally{
return readFile;
}
}
public class ProcessClearStream extends Thread {
private InputStream inputStream;
private String type;
private List files;
ProcessClearStream(InputStream inputStream, String type, List files) {
this.inputStream = inputStream;
this.type = type;
this.files = files;
}
public void run() {
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream);
BufferedReader br = new BufferedReader(inputStreamReader);
try {
// 打印信息
String line = null;
while ((line = br.readLine()) != null) {
if(type.equals("INFO")){
log.info("隨機獲取文件夾下的文件"+line);
File tempf = new File(ProComMailMutiply.oldmailbox_path+File.separator+line);
if(tempf.isFile())
{
files.add(line);
} else{
log.info(tempf+"不是文件");
}
}else{
log.error("打印錯誤輸出流 :"+line);
}
}
} catch (IOException ioe) {
log.error("搬運文件出錯了"+ioe.getMessage());
}finally {
try {
br.close();
} catch (IOException e) {
log.error("關閉文件流異常");
}
}
}
}