是否收集 Java 线程垃圾

这个问题是张贴在一些网站。我没有找到正确的答案那里,所以我张贴在这里再次。

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
}
}

我的问题不是关于停止一个线程。让我重新措辞我的问题。 行 A (参见上面的代码)启动一个新的线程; 行 B 使线程引用为空。因此,JVM 现在有一个线程对象(处于运行状态) ,对它不存在引用(在 B 行中为 t = null)。 所以我的问题是,为什么这个线程(在主线程中没有任何引用)一直运行,直到主线程运行。根据我的理解,线程对象应该在 B 行之后被垃圾收集。我尝试运行这段代码5分钟以上,请求 Java 运行时运行 GC,但是线程就是不停止。

希望这次代码和问题都清楚了。

39370 次浏览

The JVM has a reference to all running threads.

No thread (or the things it refers to) will be garbage-collected while it is still running.

A running thread is considered a so called garbage collection root and is one of those things keeping stuff from being garbage collected. When the garbage collector determines whether your object is 'reachable' or not, it is always doing so using the set of garbage collector roots as reference points.

Consider this, why is your main thread not being garbage collected, no one is referencing that one either.

The Thread is not garbage collected because there are references to the threads that you cannot see. For example, there are references in the runtime system.

When the Thread is created it is added to the current thread group. You can get a list of Threads in the current thread group, so that is another way to get a reference to it.

As was explained, running threads are, by definition, immune to GC. The GC begins its work by scanning "roots", which are deemed always reachable; roots include global variables ("static fields" in Java-talk) and the stacks of all running threads (it can be imagined that the stack of a running thread references the corresponding Thread instance).

However, you can make a thread a "daemon" thread (see Thread.setDaemon(boolean)). A daemon thread is no more garbage-collected than a non-daemon thread, but the JVM exits when all running threads are daemon. One way to imagine it is that every thread, when it terminates, checks whether there remain some non-daemon running threads; if not, the terminating thread forces a System.exit() call, which exits the JVM (killing off the running daemon threads). This is not a GC-related issue; in a way, threads are allocated manually. However, this is how the JVM can tolerate semi-rogue threads. This is typically used for Timer instances.