1. Regardez d'abord le code suivant
Importer java.io.fileInputStream; public class ttt {public static void main (String [] args) lève une exception {pour (int i = 0; i <10; i ++) {final String ThreadId = "thread_" + i; thread thread = new Thread (new Runnable () {public Void run () {System.out.printlnn (ThreadId + "a commencé!") = 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. Compilez et exécutez cette classe sur Linux, puis utilisez la commande Linux / USR / SBIN / LSOF -P <PID> pour afficher les informations de fichier ouvertes par ce programme.
$ / 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.logjava 21562 fkong 4r reg 253,0 0 35471424 /opt/test.logjava 21562 fkong 5r Reg 253,0 0 35471424 /opt/Test.Logjava 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 /opt/test.Logjava 21562 Fkong 11r 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.Logjava 21562 /opt/test.logQue ce soit pendant ou après 10 threads en cours d'exécution, les résultats de la visualisation à l'aide de la commande LSOF sont les mêmes. Vous pouvez voir que 10 flux de fichiers ne sont pas fermés.
3. J'ai apporté quelques modifications à ce code ci-dessous, c'est-à-dire après l'exécution du thread, tous les threads sont définis sur NULL, comme suit
Importer java.io.fileInputStream; Importer java.util.arraylist; import java.util.list; public class ttt {public static void main (String [] args) lève une exception {list <ired> threads = new ArrayList <file> (); pour (int i = 0; i <10; i ++) {final String Threadid = "thread_" + i; witer = newread (newreadre (newreadre Runnable () {public void run () {System.out.println (threadid + "started!"); Try {fileInputStream fis = new FileInputStream ("/ opt / test.log"); thread.sleep (60 * 1000);} capture (exception ex) "stopped!");}}); thread.start (); threads.add (thread);} thread.sleep (2 * 60 * 1000); for (thread thread: threads) {thread = null;} System.out.println ("nettoyer les threads!"); Encore une fois, utilisez LSOF pour visualiser pendant et après l'exécution des 10 threads, et les résultats sont toujours similaires, et il y a encore 10 flux de fichiers qui ne sont pas fermés.
J'ai apporté des modifications à nouveau, après avoir réglé tous les threads sur NULL, ajouter (ou exhorter le JVM) à effectuer quelques opérations GC, comme suit:
Importer java.io.fileInputStream; Importer java.util.arraylist; import java.util.list; public class ttt {public static void main (String [] args) lève une exception {list <ired> threads = new ArrayList <file> (); pour (int i = 0; i <10; i ++) {final String Threadid = "thread_" + i; witer = newread (newreadre (newreadre Runnable () {public void run () {System.out.println (threadid + "started!"); Try {fileInputStream fis = new FileInputStream ("/ opt / test.log"); thread.sleep (60 * 1000);} capture (exception ex) "Stopped!");}}); thread.start (); threads.add (thread);} thread.sleep (2 * 60 * 1000); for (thread thread: threads) {thread = null;} system.out.println ("nettoyer les threads!"); System.gc (); System.gc (); System.gc (); System.out.Println ("finir GC! "); Thread.Sleep (10 * 60 * 1000);}}Utilisez LSOF pour afficher à nouveau, et vous pouvez toujours voir que 10 flux de fichiers sont ouverts pendant l'exécution, mais après "terminé GC!", Le résultat est que les 10 flux de fichiers sont fermés.
Enfin, j'ai simplement supprimé les instructions qui définissent le thread sur NULL, et les résultats de l'exécution sont également cohérents avec les résultats de l'exécution des opérations GC ci-dessus.
En fin de compte, pour les flux de fichiers IO qui sont ouverts et non fermés dans le JVM les recycleront tous lorsqu'ils ne seront plus utilisés lorsqu'ils font GC complet la prochaine fois, mais il n'est toujours pas bon de laisser le JVM faire ces choses. Le même vieil adage est de faire vos propres affaires.