Cette question a été publiée sur un site. Je n'ai pas trouvé de bonnes réponses ici, alors je la poste à nouveau ici.
public class TestThread {
public static void main(String[] s) {
// anonymous class extends Thread
Thread t = new Thread() {
public void run() {
// infinite loop
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// as long as this line printed out, you know it is alive.
System.out.println("thread is running...");
}
}
};
t.start(); // Line A
t = null; // Line B
// no more references for Thread t
// another infinite loop
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
System.gc();
System.out.println("Executed System.gc()");
} // The program will run forever until you use ^C to stop it
}
}
Ma requête ne concerne pas l'arrêt d'un thread. Permettez-moi de reformuler ma question. La ligne A (voir code ci-dessus) démarre un nouveau thread; et la ligne B rendent la référence de thread nulle. Ainsi, la JVM a maintenant un objet Thread (qui est en cours d'exécution) auquel aucune référence n'existe (comme t = null sur la ligne B). Ma question est donc de savoir pourquoi ce thread (qui n'a plus de référence dans le thread principal) continue de fonctionner jusqu'à ce que le thread principal soit en cours d'exécution. D'après ce que j'ai compris, l'objet thread aurait dû être récupéré après la ligne B. J'ai essayé d'exécuter ce code pendant 5 minutes et plus, demandant à Java Runtime d'exécuter GC, mais le thread ne s'arrête tout simplement pas.
J'espère que le code et la question sont clairs cette fois.
child.join()
, il avait une référence àchild
. Si cette référence (et toute autre) n'est pas ignorée, le thread enfant ne peut pas être GC.Comme expliqué, les threads en cours d'exécution sont, par définition, immunisés contre GC. Le GC commence son travail en scannant les «racines», qui sont réputées toujours joignables; les racines incluent des variables globales ("champs statiques" dans Java-talk) et les piles de tous les threads en cours d'exécution (on peut imaginer que la pile d'un thread en cours d'exécution référence l'
Thread
instance correspondante ).Cependant, vous pouvez faire d'un thread un thread "démon" (voir
Thread.setDaemon(boolean)
). Un thread démon n'est pas plus récupéré qu'un thread non démon, mais la JVM se ferme lorsque tous les threads en cours d'exécution sont démon. Une façon de l'imaginer est que chaque thread, lorsqu'il se termine, vérifie s'il reste des threads non démon en cours d'exécution; sinon, le thread de fin force unSystem.exit()
appel, qui quitte la JVM (tuant les threads de démon en cours d'exécution). Ce n'est pas un problème lié au GC; d'une certaine manière, les threads sont alloués manuellement. Cependant, c'est ainsi que la JVM peut tolérer les threads semi-escrocs. Ceci est généralement utilisé pour lesTimer
instances.la source
La JVM a une référence à tous les threads en cours d'exécution.
Aucun thread (ou les choses auxquelles il fait référence) ne sera récupéré pendant qu'il est encore en cours d'exécution.
la source
Le thread n'est pas garbage collection car il existe des références aux threads que vous ne pouvez pas voir. Par exemple, il existe des références dans le système d'exécution.
Lorsque le thread est créé, il est ajouté au groupe de threads actuel. Vous pouvez obtenir une liste de threads dans le groupe de threads actuel, c'est donc une autre façon d'obtenir une référence à celui-ci.
la source