2

I have a class that contains a Thread as a field, and when the class gets garbage collected the thread keeps running, which I don't want to happen.

Like this:

public class A
{
    Thread thread;

    public A()
    {
        thread = new Thread() {
            @Override
            public void run()
            {
                while(!isInterrupted())
                {
                    //Do work
                }
            }
        };

        thread.start();
    }
}

But when A goes away, the thread lives on. I've read about using the finalize method but it's always discouraged. What's the correct way to handle this?

Jason C
  • 38,729
  • 14
  • 126
  • 182
Name McChange
  • 2,750
  • 5
  • 27
  • 46

1 Answers1

3

Live threads are considered a garbage collector root, so even when your A is gone the thread sticks around (as do any objects that said Thread holds references to, by the way).

Also even if the thread itself was subject to GC, it would be tricky business to have the GC terminate it gracefully.

There isn't really a way to terminate the thread automatically, and I'd advise against finalize for various reasons (note also that if your thread happens to hold a reference to your A instance then A's finalize will definitely never get called, as your A will never be garbage collected).

Instead, terminate the thread explicitly when you are done with it. It is the only really safe and predictable option there.

For example, you may expose a stop() or finish() or whatever method from A that stops the thread, and document the requirement to call it when you are done with it, just like you have to, say, close files and streams when you are done with them, e.g. building on your snippet:

public class A {

    Thread thread;

    public A () {
        thread = new Thread() {
            @Override public void run() {
                while(!isInterrupted()) {
                    //Do work
                }
            }
        };
        thread.start();
    }

    void stop () {
        thread.interrupt();
        thread.join(); // if you want
    }

}

If you have A implement AutoCloseable and stop the thread in close() then you also get the bonus of being able to use try-with-resources for cleanup.

Further reading on the garbage collector's behavior wrt threads:

Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182
  • Yeah, I was hoping I wouldn't have to manually call a stop method or anything but oh well. – Name McChange Mar 05 '17 at 00:02
  • @NameMcChange Yes, it is somewhat irritating, but it is also par for the course in a language like Java so on the bright side nobody will really bat an eye at it. It's a pretty typical practice and shouldn't cause confusion to readers of your code. – Jason C Mar 05 '17 at 00:03