Daemon Threads

Beginner
Processes & Threads

Daemon threads are background threads that serve other threads and do not prevent the JVM from exiting when all non-daemon threads have finished.

Overview

In Java, every thread is either a user thread (non-daemon) or a daemon thread. The JVM exits when all non-daemon threads complete — it does not wait for daemon threads to finish. Daemon threads are designed for background housekeeping tasks: the garbage collector, the finalizer, and JVM internal threads are all daemons. You mark a thread as a daemon by calling setDaemon(true) before starting it. If you forget to call it before start(), you get an IllegalThreadStateException. Use daemon threads for tasks that should not block JVM shutdown: heartbeat monitors, log flushers, cache eviction loops, and background metrics collectors. Be careful: daemon threads are abruptly terminated at JVM exit — any in-progress I/O or file writes may be left incomplete.

Daemon vs User Threads: JVM Exit Behaviour

The JVM exit condition is: all non-daemon threads have completed. Daemon threads are like service staff — they stay running as long as there are guests (user threads), but when the last guest leaves, the staff is dismissed immediately regardless of what they are doing. This is why you should never do critical work (file I/O, DB writes) in a daemon thread.

Java — daemon thread killed when last user thread exits
// Daemon thread example — JVM exits even while daemon is "running"
Thread daemon = new Thread(() -> {
    while (true) {
        try {
            System.out.println("Daemon: heartbeat ping at " + Instant.now());
            Thread.sleep(500);
        } catch (InterruptedException e) {
            System.out.println("Daemon interrupted — JVM shutting down");
            break;
        }
    }
});
daemon.setDaemon(true);     // MUST be called before start()
daemon.start();

// Non-daemon (user) thread
Thread userThread = new Thread(() -> {
    try {
        System.out.println("User thread: doing work...");
        Thread.sleep(1500);     // simulate 1.5 seconds of work
        System.out.println("User thread: done.");
    } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});
userThread.start();
userThread.join();
// After userThread ends, JVM exits — daemon is killed mid-heartbeat

Practical Daemon Thread Use Cases

Daemon threads are perfect for tasks that are best-effort and can be abandoned safely: periodic log flushing, cache cleanup, background metrics, and connection pool heartbeats. Using virtual threads (Java 21), you can create daemon virtual threads with Thread.ofVirtual().daemon(true) — useful for lightweight background monitoring tasks.

Java — cache eviction daemon + Thread.ofPlatform() builder API
// Background cache eviction daemon
Thread evictionDaemon = Thread.ofPlatform()
    .daemon(true)
    .name("cache-eviction")
    .start(() -> {
        Map<String, Instant> cache = new ConcurrentHashMap<>();
        while (!Thread.currentThread().isInterrupted()) {
            try {
                // Remove entries older than 60 seconds
                Instant cutoff = Instant.now().minusSeconds(60);
                cache.entrySet().removeIf(e -> e.getValue().isBefore(cutoff));
                System.out.println("Cache eviction pass: " + cache.size() + " entries remaining");
                Thread.sleep(10_000);   // run every 10 seconds
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    });

// Check daemon status
System.out.println("Is daemon: " + evictionDaemon.isDaemon());  // true

// Java 21 virtual daemon thread for lightweight monitoring
Thread virtualDaemon = Thread.ofVirtual().name("monitor").start(() -> {
    // lightweight background polling — daemon by default for virtual threads? No —
    // virtual threads are non-daemon by default, set explicitly if needed
    Thread.currentThread().setDaemon(true); // not valid post-start — use builder
});

Key Points to Remember

  • 1Daemon threads do not prevent JVM exit — the JVM exits when all non-daemon threads complete.
  • 2setDaemon(true) must be called before start(); calling it after throws IllegalThreadStateException.
  • 3The JVM's garbage collector, finalizer, and internal JVM threads are all daemon threads.
  • 4Never perform critical I/O or writes in a daemon thread — it may be killed abruptly.
  • 5Use daemon threads for heartbeats, monitoring, log flushing, and cache eviction.
  • 6Java's Thread.ofPlatform().daemon(true) builder API is the modern way to create daemon threads.

Interview Questions

Sign in to ask Aria
1

What is a daemon thread and how does it differ from a user thread?

EasyAmazon
2

What happens to a daemon thread when the last user thread finishes?

EasyFlipkart
3

Why should you not perform database writes inside a daemon thread?

MediumGoogle
4

Can a thread spawned by a daemon thread be a user thread?

HardMicrosoft

Ask Aria about Daemon Threads

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…