1. ก่อนอื่นดูรหัสต่อไปนี้
นำเข้า java.io.fileinputstream; คลาสสาธารณะ ttt {โมฆะคงที่สาธารณะหลัก (สตริง [] args) พ่นข้อยกเว้น {สำหรับ (int i = 0; i <10; i ++) {สตริงสุดท้าย ThreadId = "Thread_" + i; เธรด Thread = Thread ใหม่ = ใหม่ FileInputStream ("/opt/test.log"); thread.sleep (60 * 1000);} catch (Exception ex) {ex.printstacktrace ();} system.out.println (threadid + "หยุด!");}}); thread.start ();2. รวบรวมและเรียกใช้คลาสนี้บน Linux จากนั้นใช้คำสั่ง Linux/USR/SBIN/LSOF -P <PID> เพื่อดูข้อมูลไฟล์ที่เปิดโดยโปรแกรมนี้
$/USR/SBIN/LSOF -P `PS -EF | Grep Java | grep ttt | awk '{พิมพ์ $ 2}' `| grep "test.log" Java 21562 fkong 3r reg 253,0 0 35471424 /opt/test.logjava 21562 fkong 4r Reg 253,0 0 35471424 /opt/test.logjava 21562 21562 fkong 6r Reg 253,0 0 35471424 /opt/test.logjava 21562 fkong 7r Reg 253,0 0 35471424 /opt/test.logjava 21562 Fkong 8r Reg 253,0 0 35471424 253,0 0 35471424 /opt/test.logjava 21562 fkong 11r Reg 253,0 0 35471424 /opt/test.logjava 21562 FKONG 11R Reg 253,0 0 35471424 /opt/test.logไม่ว่าจะเป็นในระหว่างหรือหลัง 10 เธรดที่ทำงานผลลัพธ์ของการดูโดยใช้คำสั่ง LSOF จะเหมือนกัน คุณจะเห็นว่าสตรีมไฟล์ 10 รายการไม่ได้ปิด
3. ฉันได้ทำการเปลี่ยนแปลงบางอย่างในรหัสนี้ด้านล่างนั่นคือหลังจากที่เธรดดำเนินการแล้วเธรดทั้งหมดจะถูกตั้งค่าเป็น NULL ดังนี้
นำเข้า java.io.fileinputstream; นำเข้า java.util.arraylist; นำเข้า java.util.list; คลาสสาธารณะ ttt {โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {รายการ <เธรด> เธรด = ใหม่ runnable () {public void run () {system.out.println (threadid + "เริ่มต้น!"); ลอง {fileinputstream fis = ใหม่ fileinputstream ("/opt/test.log"); thread.sleep (60 * 1000); "หยุด!");}}); thread.start (); threads.add (เธรด);} thread.sleep (2 * 60 * 1000); สำหรับ (เธรดด้าย: เธรด) {เธรด = null;} system.out.println ("ทำความสะอาดเธรด!"); อีกครั้งใช้ LSOF เพื่อดูระหว่างและหลังการทำงาน 10 เธรดและผลลัพธ์ยังคงคล้ายกันและยังมีสตรีมไฟล์ 10 รายการที่ไม่ได้ปิด
ฉันทำการเปลี่ยนแปลงอีกครั้งหลังจากตั้งค่าเธรดทั้งหมดเป็น NULL เพิ่ม (หรือกระตุ้น JVM) ให้ดำเนินการ GC สองสามครั้งดังนี้:
นำเข้า java.io.fileinputstream; นำเข้า java.util.arraylist; นำเข้า java.util.list; คลาสสาธารณะ ttt {โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {รายการ <เธรด> เธรด = ใหม่ runnable () {public void run () {system.out.println (threadid + "เริ่มต้น!"); ลอง {fileinputstream fis = ใหม่ fileinputstream ("/opt/test.log"); thread.sleep (60 * 1000); "หยุด!");}}); thread.start (); threads.add (เธรด);} thread.sleep (2 * 60 * 1000); สำหรับ (เธรดด้าย: เธรด) {เธรด = null;} system.out.println ("ทำความสะอาดเธรด!"); system.gc (); gc! "); thread.sleep (10 * 60 * 1000);}}ใช้ LSOF เพื่อดูอีกครั้งและคุณยังสามารถเห็นได้ว่าสตรีมไฟล์ 10 ไฟล์เปิดอยู่ระหว่างการทำงาน แต่หลังจาก "เสร็จสิ้น GC!" ผลลัพธ์คือการปิดไฟล์ 10 ไฟล์
ในที่สุดฉันเพียงแค่ลบข้อความที่ตั้งเธรดเป็น NULL และผลลัพธ์ของการรันก็สอดคล้องกับผลลัพธ์ของการดำเนินการ GC ด้านบน
ในท้ายที่สุดสำหรับสตรีมไฟล์ IO ที่เปิดอยู่และไม่ปิดใน JVM จะรีไซเคิลพวกเขาทั้งหมดเมื่อพวกเขาไม่ได้ใช้อีกต่อไปเมื่อพวกเขาทำ GC เต็มในครั้งต่อไป แต่ก็ยังไม่ดีที่จะปล่อยให้ JVM ทำสิ่งเหล่านี้ คำพูดเก่า ๆ เดียวกันคือการทำสิ่งของของคุณเอง