Backend Development 13 min read

Understanding User Threads and Daemon Threads in Java

This article explains the differences between user threads and daemon (background) threads in Java, demonstrates how to identify, create, and configure them—including thread pools—and discusses important considerations, priority effects, and typical use cases such as garbage collection.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Understanding User Threads and Daemon Threads in Java

In Java, threads are divided into two categories: user (non‑daemon) threads and daemon (background) threads, a distinction that is often overlooked. By default, both the main thread and any newly created thread are user threads, which can be verified using the isDaemon() method.

Identifying thread type : calling Thread.currentThread().isDaemon() returns false for user threads. Example code demonstrates this check.

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("我是子线程");
        }
    });
    System.out.println("子线程==守护线程:" + thread.isDaemon());
    System.out.println("主线程==守护线程:" + Thread.currentThread().isDaemon());
}

The output shows that both the main thread and the newly created thread are user threads.

Converting a thread to a daemon : Use setDaemon(true) before start() to turn a user thread into a daemon thread. For thread pools, a custom ThreadFactory must set each worker thread as daemon.

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("我是子线程");
        }
    });
    // Set as daemon
    thread.setDaemon(true);
    System.out.println("子线程==守护线程:" + thread.isDaemon());
    System.out.println("主线程==守护线程:" + Thread.currentThread().isDaemon());
}

For a thread pool:

ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        // Set thread as daemon
        t.setDaemon(true);
        return t;
    }
});

Daemon vs. User thread behavior : A daemon thread runs in the background and terminates automatically when all user threads finish. Demonstrations show that a daemon thread may not complete its work unless the main thread waits (e.g., using join() ).

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 1; i <= 10; i++) {
                System.out.println("i:" + i);
                try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }
            }
        }
    });
    thread.setDaemon(true);
    thread.start();
    thread.join(); // Wait for daemon thread to finish
    System.out.println("子线程==守护线程:" + thread.isDaemon());
    System.out.println("主线程==守护线程:" + Thread.currentThread().isDaemon());
}

When join() is used, the program waits for the daemon thread to finish before exiting.

Important considerations :

Calling setDaemon(true) must occur before start() ; otherwise an IllegalThreadStateException is thrown and the daemon flag is ignored.

Threads created inside a daemon thread inherit the daemon status by default.

The join() method forces the JVM to wait for a daemon thread, contrary to the usual automatic termination.

Priority : Thread type (daemon vs. user) does not affect scheduling priority. Changing a thread’s priority (e.g., setPriority(Thread.MAX_PRIORITY) ) influences execution order regardless of daemon status.

Typical use cases : Daemon threads are ideal for non‑essential background services such as garbage collection or health‑check monitors that should not prevent the JVM from shutting down once all user threads complete.

Summary : Daemon threads serve user threads and terminate automatically when no user threads remain. They have lower business‑logic importance but the same scheduling priority as user threads. Common scenarios include garbage collection and auxiliary server tasks, and child threads of a daemon inherit the daemon flag.

JavaConcurrencyThreadPoolThread PriorityDaemon ThreadUser Thread
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.