Please help me find the reason for Thread leak in the code below. The TestThread does not get garbage collected even after run() has completed (verified from the consoled print statement) and the main method has exited (verified from print statement and profiler tool).
The TestThread, however, gets garbage collected if it is set as a Daemon Thread i.e. t.setDaemon(true). The code below is just a sample code which illustrates the problem in my application. I’m trying to use some pre-existing scheduling class (which was designed by someone else using ScheduledExecutorService). I notice that when I keep scheduling multiple Runnables with the class, the created threads never get garbage collected.
public class ThreadTest {
static void runThreadWithExecutor() {
final String name = "TestThread";
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, name);
t.setDaemon(false);
return t;
}
});
ses.schedule(new Runnable() {
@Override
public void run() {
System.out.println("entered " + name);
System.out.println("exiting " + name);
}},
2,
TimeUnit.SECONDS);
}
public static void main(String[] args) throws InterruptedException {
System.out.println("entered main");
runThreadWithExecutor();
Thread.sleep(5000);
System.out.println("exiting main");
}
}
This is due to the fact that you are not calling
shutdown()on your executor service after you have scheduled your last job:I just added the
shutdown()call to your code and it exits fine. This is true of allExecutorServices. Without the shutdown the thread pool continues to wait for more jobs to be submitted and is never GC’d.See @John’s answer below for more details.