Java Notes
Complete guide to Daemon Threads in Java — what they are, how they differ from user threads, JVM shutdown behavior, practical use cases like GC and auto-save, and common pitfalls.
What is a Daemon Thread?
A daemon thread is a low-priority background thread that provides services to user threads. The key characteristic: the JVM exits when only daemon threads remain alive.
Think of daemon threads as background services:
- They support the main work (user threads)
- They don't prevent the program from exiting
- They're abruptly terminated when the JVM shuts down
User Threads vs Daemon Threads
| Feature | User Thread | Daemon Thread |
|---|---|---|
| JVM waits for it? | YES | NO |
| Purpose | Main application work | Background services |
| Shutdown | Runs to completion | Abruptly killed |
| Default | All new threads | Must explicitly set |
| Examples | main, workers | GC, auto-save, logging |
Creating Daemon Threads
Output:
| isDaemon | true |
| Main thread is daemon | false |
| [Daemon] Background tick | 1 |
| [Daemon] Background tick | 2 |
| [Daemon] Background tick | 3 |
| [Daemon] Background tick | 4 |
Notice: The daemon was in an infinite loop, but the program still exits when main finishes!
Daemon vs Non-Daemon Comparison
Output:
The daemon only got to step 4-5 before the JVM shut down (after user thread finished).
Real-World Use Case: Auto-Save Service
Output:
| [Edit] Added | "Hello World" (v1) |
| [Edit] Added | "Adding second paragraph" (v2) |
| [Edit] Added | "Fixing typos" (v3) |
| [Edit] Added | "Final changes" (v4) |
Real-World Use Case: Heartbeat Monitor
=== Heartbeat Monitor (Daemon) === [Main] Application running... [Monitor] ❤️ Heartbeat OK (1s interval) [Monitor] ❤️ Heartbeat OK [Monitor] ❤️ Heartbeat OK [Main] Application finished. (Monitor daemon thread stops - JVM exits)
Important Rules and Pitfalls
public class DaemonRules {
public static void main(String[] args) {
System.out.println("=== Daemon Thread Rules ===\n");
// Rule 1: Must set daemon BEFORE start()
Thread t = new Thread(() -> {});
t.setDaemon(true); // ✅ OK — before start
t.start();
try {
t.setDaemon(false); // ❌ IllegalThreadStateException!
} catch (IllegalThreadStateException e) {
System.out.println("Rule 1: Cannot setDaemon after start()");
System.out.println(" Error: " + e.getClass().getSimpleName());
}
// Rule 2: Daemon inherits from parent
Thread.currentThread().setName("MainUser");
Thread child = new Thread(() -> {
System.out.println("\nRule 2: Child inherits daemon status from parent");
System.out.println(" Parent (main) isDaemon: " + false);
System.out.println(" Child isDaemon: " + Thread.currentThread().isDaemon());
});
child.start();
try { child.join(); } catch (InterruptedException e) {}
// Rule 3: Daemon threads should NOT do critical I/O
System.out.println("\nRule 3: Don't do critical work in daemon threads!");
System.out.println(" Daemons can be killed mid-operation.");
System.out.println(" Never: write critical data, commit transactions");
System.out.println(" OK: logging, monitoring, caching, GC");
// Rule 4: finally blocks may not execute in daemon threads
System.out.println("\nRule 4: finally blocks in daemons are NOT guaranteed!");
System.out.println(" JVM can kill daemon without running finally.");
}
}=== Daemon Thread Rules === Rule 1: Cannot setDaemon after start() Result: IllegalThreadStateException ✓ Rule 2: Daemon thread inherits parent's daemon status Child of daemon is daemon: true Child of user thread is user: true Rule 3: JVM exits when only daemon threads remain User thread done. JVM will exit shortly. (Daemon work may be incomplete)
Common Mistakes
1. Setting daemon after start()
Thread t = new Thread(() -> {});
t.start();
t.setDaemon(true); // ❌ IllegalThreadStateException!2. Doing critical work in daemon threads
// ❌ BAD: File write might be cut short!
Thread saver = new Thread(() -> {
// This might never complete — daemon can be killed anytime!
writeToFile(importantData);
});
saver.setDaemon(true);
saver.start();3. Assuming finally blocks execute in daemon threads
Thread daemon = new Thread(() -> {
try {
while (true) { Thread.sleep(100); }
} finally {
// ❌ This may NEVER execute!
releaseResources();
}
});
daemon.setDaemon(true);Interview Questions
Q1: What is a daemon thread?
Answer: A daemon thread is a background service thread that doesn't prevent the JVM from exiting. When all user (non-daemon) threads finish, the JVM terminates and all daemon threads are killed immediately. Examples: Garbage Collector, Finalizer thread.
Q2: How do you create a daemon thread?
Answer: Call thread.setDaemon(true) BEFORE calling thread.start(). Setting it after start throws IllegalThreadStateException.
Q3: What happens to daemon threads when the JVM shuts down?
Answer: They are immediately and abruptly terminated. No finally blocks are guaranteed to run, no shutdown hooks are called for them specifically. Any I/O operation in progress may be left incomplete.
Q4: Can the main thread be a daemon thread?
Answer: No. The main thread is always a user (non-daemon) thread. You cannot call setDaemon(true) on it because it's already started.
Q5: Do child threads inherit the daemon status of their parent?
Answer: Yes. A thread created by a daemon thread is also a daemon. A thread created by a user thread is also a user thread. You can override this by calling setDaemon() before start().
Q6: When should you use daemon threads?
Answer: For background services that support the main application but shouldn't keep it alive: auto-save, heartbeat monitoring, cache cleanup, garbage collection, log flushing, session timeout checking. Never for critical data writes or transactions.
Q8: What happens to daemon thread's finally block when JVM shuts down?
A: It does NOT execute! When all user threads finish, the JVM exits immediately, killing all daemon threads without running their finally blocks. This is a critical difference — never put important cleanup (file saves, database commits) in daemon threads because there's no guarantee they'll complete.
Q9: Can you change a thread's daemon status after it has started?
A: No. Calling setDaemon() after start() throws IllegalThreadStateException. Daemon status must be set before the thread starts. Once running, a thread's daemon/user classification is fixed for its lifetime.
Q10: What are real-world examples of daemon threads in Java?
A: (1) Garbage Collector — reclaims memory in background. (2) Signal dispatcher thread. (3) Finalizer thread. (4) JMX monitoring threads. (5) Timer threads for housekeeping. In applications: (6) Log flushing, (7) Cache cleanup, (8) Heartbeat/health-check threads, (9) Auto-save background threads.
Q11: Do child threads inherit daemon status from parent?
A: Yes! A new thread inherits the daemon status of the thread that creates it. If a daemon thread creates a child thread, that child is also a daemon by default. If a user thread creates a child, it's a user thread. Override with setDaemon() before start().
Q12: What is the relationship between daemon threads and thread pools?
A: By default, ExecutorService creates user threads (preventing JVM shutdown). To create daemon thread pools, provide a custom ThreadFactory: Executors.newFixedThreadPool(4, r -> { Thread t = new Thread(r); t.setDaemon(true); return t; }). Use daemon pools for non-critical background tasks.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Daemon Threads in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, multithreading, daemon, thread
Related Java Master Course Topics