文件夾目錄下文件太多,list直接卡住的解決方式

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("關閉文件流異常");
				}
			}
		}
	}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章