Daemon threads and thread factories
Decide which threads keep the JVM alive, name them properly, and catch what escapes them.
Open this lesson in the learning hubKey points
- The JVM exits when the last non-daemon thread ends. Daemon threads are then killed outright, with no finally blocks.
setDaemon(true)must be called beforestart(). Use it for background helpers, never for work that must complete.- A new thread inherits the daemon flag and the priority of the thread that created it.
- Give threads names with a
ThreadFactory. Unnamed pool threads turn every thread dump into guesswork. - An exception escaping a task kills only that thread, and quietly. Set an uncaught exception handler so it is at least logged.
Example
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread.setDefaultUncaughtExceptionHandler(
(t, e) -> System.out.println("uncaught in " + t.getName() + " : " + e.getMessage()));
Thread boom = new Thread(() -> { throw new IllegalStateException("task blew up"); }, "boom");
boom.start();
boom.join(); // only that thread died, the JVM carried on
Thread heartbeat = new Thread(() -> { for (int i = 0; i < 40; i++) sleep(50); }, "heartbeat");
heartbeat.setDaemon(true); // must be set BEFORE start()
heartbeat.start();
ThreadFactory named = new ThreadFactory() {
private final AtomicInteger n = new AtomicInteger(1);
@Override public Thread newThread(Runnable r) {
Thread t = new Thread(r, "orders-" + n.getAndIncrement());
t.setDaemon(false); // real work: keep the JVM alive until it finishes
return t;
}
};
ExecutorService pool = Executors.newFixedThreadPool(2, named);
for (int i = 0; i < 3; i++) {
pool.execute(() -> System.out.println("job ran on : " + Thread.currentThread().getName()));
}
pool.shutdown();
pool.awaitTermination(2, TimeUnit.SECONDS);
System.out.println("heartbeat : daemon=" + heartbeat.isDaemon() + ", alive=" + heartbeat.isAlive());
System.out.println("main ends : the JVM exits anyway and the daemon dies with it");
}
static void sleep(long ms) { try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }
}
Name every thread, and make it a daemon only if losing its work is acceptable.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.