Java Thread Garbage collected or not

2019-01-01 13:22发布

问题:

This question was posted on some site. I didnt find right answers there, so I am posting it here again.

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

My query is not about stopping a Thread. Let me rephrase my question. Line A(see code above) starts a new Thread; and Line B make the thread reference null. So, the JVM now has a Thread Object(which is in running state) to which no reference exists (as t=null in Line B). So my question is, why does this thread(that has no reference anymore in the main thread) keeps on running until the main thread is running. Per my understanding, the thread object should have been garbage collected post Line B. I tried to run this code for 5 minutes and more, requesting Java Runtime to run GC, but the thread just does not stop.

Hope both the code and question is clear this time.

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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.