skip to content

Daemon Threads & Uncaught Exceptions

Daemon threads do not keep the JVM alive, so setDaemon before start decides whether your background worker blocks shutdown. UncaughtExceptionHandler is the companion topic: where an exception goes when it escapes run().

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What is the difference between a daemon thread and a user thread in Java, and how do you make a thread a daemon?

level: juniorimportance: should knowfreq 55%

answer

  1. User thread keeps JVM alive; daemon does not
  2. JVM exits when last user thread ends
  3. setDaemon(true) BEFORE start()
  4. After start() -> IllegalThreadStateException
  5. New thread inherits creator's daemon flag

basics

~20 s

A user thread keeps the program alive; the JVM waits for all user threads to finish before exiting. A daemon thread is a background helper that does not keep the program alive. Call thread.setDaemon(true) before start() to make one.

solid answer

~50 s

Java threads are either user threads (the default) or daemon threads. The JVM stays alive as long as at least one user thread is running; it only exits once the last user thread finishes. Daemon threads, by contrast, are background helpers — the JVM does not wait for them and abandons them when all user threads are done. You mark a thread as daemon with setDaemon(true), which must be called before start() (otherwise it throws IllegalThreadStateException). A new thread inherits the daemon status of the thread that creates it, so threads spawned by the main thread are user threads by default. Daemons suit fire-and-forget background work like housekeeping, monitoring, or GC-style tasks where abrupt termination is acceptable. Avoid daemons for work that must complete or that holds resources needing clean shutdown, because daemons are killed without running finally blocks or releasing resources when the JVM exits.

code

java · 17 lines
java
public class DaemonDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread worker = new Thread(() -> {
            while (true) {
                System.out.println("daemon working...");
                try { Thread.sleep(200); } catch (InterruptedException e) { return; }
            }
        });
        worker.setDaemon(true);   // MUST be before start()
        worker.start();

        Thread.sleep(500);
        System.out.println("main ending");
        // main (the only user thread) returns here -> JVM exits,
        // abandoning the daemon mid-loop without further output.
    }
}

go deeper

for a junior

Knows the default is a user thread, that setDaemon(true) must precede start(), and that daemons do not keep the JVM alive.

for a middle

Explains JVM-exit semantics precisely (last user thread), the IllegalThreadStateException on late setDaemon, and gives appropriate daemon use cases.

for a senior

Discusses inheritance of the daemon flag, the abrupt-termination/no-cleanup hazard, and why daemons are unsuitable for resource-holding or must-complete work.

for a principal

Frames daemon usage in lifecycle/shutdown design — prefers explicit shutdown coordination (executor shutdown, shutdown hooks) over relying on daemon abandonment, and reasons about data-loss risk at process exit.

## Terms first A **thread** is an independent path of execution within a running Java program; a single JVM process can run many threads at once. The **JVM** (Java Virtual Machine) is the process that runs your program; when it has nothing left to do it **exits** (the process ends). Every Java thread is classified as one of two kinds: - **User thread** (also called a non-daemon thread): the *default*. It represents real, foreground work. - **Daemon thread**: a *background* helper thread. ## The one rule that defines the difference The JVM keeps running **as long as at least one user (non-daemon) thread is alive**. The moment the **last user thread finishes**, the JVM begins to shut down — and it does **not** wait for any daemon threads. Any still-running daemon threads are simply **abandoned** (stopped abruptly). So the practical meaning is: *user threads keep the application alive; daemon threads do not.* The `main` thread that runs your `main` method is itself a user thread, which is why a simple program stays alive until `main` returns (and until any other user threads it started also finish). ## How you make a thread a daemon You call `setDaemon(true)` on a `Thread` object **before** you call `start()`: ```java Thread t = new Thread(task); t.setDaemon(true); // must be BEFORE start() t.start(); ``` If you call `setDaemon(...)` *after* the thread has already started, Java throws `IllegalThreadStateException`. The daemon flag is fixed for the life of the thread once it is running. ## Inheritance of the flag A newly created thread **inherits the daemon status of the thread that created it**. The `main` thread is a user thread, so any thread you create from `main` is a user thread by default — you must explicitly opt into daemon status. A thread created *by* a daemon thread will itself be a daemon unless you change it. ## When to use which Use **daemon** threads for *fire-and-forget* background services where abrupt termination at JVM exit is acceptable: periodic monitoring, metrics flushing on a best-effort basis, cache eviction, watchdogs, the JVM's own GC and finalizer threads are daemons. Use **user** threads for any work that *must complete* before the program can correctly exit — for example writing a file, committing a transaction, or anything that must run cleanup. ## The danger of daemons When the JVM exits because the last user thread finished, daemon threads are stopped **without** running their `finally` blocks or releasing resources cleanly — there is no graceful unwinding. So never rely on a daemon to flush important data or close critical resources; that work can be lost mid-operation. ## Quick mental model Think of a daemon thread as a janitor in an office building: useful while people (user threads) are there, but the moment the last employee leaves, the building locks up and the janitor is sent home immediately, whether or not they finished mopping.

  • What happens to a daemon thread's finally block when the JVM exits because the last user thread ended?
    It may not run at all. Daemon threads are abruptly terminated at JVM exit without guaranteed stack unwinding, so finally blocks and resource cleanup can be skipped — which is why daemons must not be used for critical cleanup.
  • If main spawns a non-daemon thread that loops forever, does the JVM exit when main returns?
    No. main returning does not end the JVM while another user (non-daemon) thread is still alive. The JVM keeps running until that looping user thread terminates.

Daemon threads are like a hotel's background music: it plays while guests (user threads) are around, but the moment the last guest checks out, the hotel powers down and the music just stops mid-song — nobody waits for it to finish.

saying these in an interview costs you the question

  • Saying daemon threads run with lower priority — daemon status is unrelated to priority
  • Thinking you can call setDaemon after start()
  • Believing the JVM waits for daemon threads to finish
  • Assuming a daemon's finally blocks always run at JVM exit (they may not)

context

open as a page

What happens when an exception escapes a thread's run() method, and how does UncaughtExceptionHandler let you handle it?

level: middleimportance: should knowfreq 60%

basics

~20 s

If an exception is thrown and not caught inside run(), it propagates out and kills only that thread — the rest of the program keeps running. You can register an UncaughtExceptionHandler (per thread or a default for all threads) to log or react to such failures instead of just printing a stack trace.

open as a page

Why is it dangerous to rely on a daemon thread for resource cleanup or flushing data, and what should you use instead?

level: seniorimportance: should knowfreq 45%

basics

~20 s

When the last user thread finishes, the JVM exits and kills daemon threads abruptly — without running their finally blocks or letting them finish current work. So a daemon flushing a buffer or closing a file may be stopped mid-operation and lose data. Use explicit shutdown (executor shutdown, shutdown hooks, or user threads) for work that must complete.

open as a page

Why must setDaemon(true) be called before start(), and what does a freshly created thread's daemon status default to?

level: middleimportance: nice to knowfreq 35%

basics

~20 s

Once a thread is running, the JVM has already decided whether it counts toward keeping the program alive, so you can't change it — calling setDaemon after start() throws IllegalThreadStateException. A new thread defaults to the daemon status of whichever thread created it.

open as a page

Walk through exactly how the JVM decides when to exit based on running threads, and how shutdown hooks, daemons, and System.exit interact during that sequence.

level: principalimportance: nice to knowfreq 28%

basics

~20 s

The JVM exits once no user (non-daemon) threads are left running, or when something calls System.exit(). At that point it runs all registered shutdown hooks, and only after those finish does it stop daemon threads and end the process. Daemons never delay exit; hooks get a window to clean up.

open as a page