Java文件流封閉和渣滓收受接管機制。本站提示廣大學習愛好者:(Java文件流封閉和渣滓收受接管機制)文章只能為提供參考,不一定能成為您想要的結果。以下是Java文件流封閉和渣滓收受接管機制正文
1.先看以下一段代碼
import java.io.FileInputStream; public class TTT { public static void main(String[] args) throws Exception { for (int i = 0; i < 10; i++) { final String threadId = "thread_" + i; Thread thread = new Thread(new Runnable() { public void run() { System.out.println(threadId + " started!"); try { FileInputStream fis = new FileInputStream("/opt/test.log"); Thread.sleep(60 * 1000); } catch (Exception ex) { ex.printStackTrace(); } System.out.println(threadId + " stopped!"); } }); thread.start(); } Thread.sleep(10 * 60 * 1000); } }
2.在linux上編譯並運轉這個類,然後應用linux的敕令/usr/sbin/lsof -p <pid>來檢查這個法式翻開的文件信息
$ /usr/sbin/lsof -p `ps -ef | grep java | grep TTT | awk '{print $2}'` | grep "test.log" java 21562 fkong 3r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 4r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 5r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 6r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 7r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 8r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 9r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 10r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 11r REG 253,0 0 35471424 /opt/test.log java 21562 fkong 12r REG 253,0 0 35471424 /opt/test.log
不論是在10個線程運轉進程中照樣運轉完,應用lsof敕令檢查的成果都一樣,都可以看到有10個文件流沒有封閉。
3.上面我把這個代碼做了一些修改,就是在線程履行完以後,將一切線程置為null,以下
import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; public class TTT { public static void main(String[] args) throws Exception { List<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 10; i++) { final String threadId = "thread_" + i; Thread thread = new Thread(new Runnable() { public void run() { System.out.println(threadId + " started!"); try { FileInputStream fis = new FileInputStream("/opt/test.log"); Thread.sleep(60 * 1000); } catch (Exception ex) { ex.printStackTrace(); } System.out.println(threadId + " stopped!"); } }); thread.start(); threads.add(thread); } Thread.sleep(2 * 60 * 1000); for (Thread thread : threads) { thread = null; } System.out.println("Clean up threads!"); Thread.sleep(10 * 60 * 1000); } }
再次在10個線程運轉進程中和運轉終了後應用lsof檢查,成果依然相似,照樣有10個文件流沒有封閉。
我再次做了一些修改,在將一切線程置為null今後,增長(或許說是敦促JVM)做幾回gc操作,以下:
import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; public class TTT { public static void main(String[] args) throws Exception { List<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 10; i++) { final String threadId = "thread_" + i; Thread thread = new Thread(new Runnable() { public void run() { System.out.println(threadId + " started!"); try { FileInputStream fis = new FileInputStream("/opt/test.log"); Thread.sleep(60 * 1000); } catch (Exception ex) { ex.printStackTrace(); } System.out.println(threadId + " stopped!"); } }); thread.start(); threads.add(thread); } Thread.sleep(2 * 60 * 1000); for (Thread thread : threads) { thread = null; } System.out.println("Clean up threads!"); System.gc(); System.gc(); System.gc(); System.out.println("Finished GC!"); Thread.sleep(10 * 60 * 1000); } }
再次應用lsof檢查,在運轉中依然照樣可以看到那有10個文件流翻開著,然則在“Finished GC!”以後,看到的成果是那10個翻開的文件流都被封閉了。
最初,我爽性把那些設置thread為null的語句刪除,運轉的成果也和下面履行gc操作的成果分歧。
終究,JVM中關於那些翻開了沒有封閉的IO文件流,會在不再被應用的情形下,比及下次做Full GC的時刻把他們全體收受接管,然則讓JVM去干這些事總清償是欠好的,照樣那句老話,本身的工作本身做。