Preface

There are two types of threads in java, user threads and daemon threads.

User threads are high priority threads and the JVM will wait for all the User Threads to finish running before it finishes running.

daemon threads are low-priority threads that serve User Threads. Because daemon threads are low priority and serve only user threads, the JVM will automatically exit when all user threads are finished, regardless of whether there are still daemon threads running.

Because of this feature, we usually handle infinite loops in daemon threads because they do not affect the operation of user threads.

The use of daemon threads is not recommended for I/O operations.

However, there are some improper operations that can cause daemon threads to block the JVM shutdown, such as calling the join() method in a daemon thread.

Application

Let’s look at how to create a daemon thread.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class DaemonThread extends Thread{

    public void run(){
        while(true){
            log.info("Thread A run");
            try {
                log.info("Thread A is daemon {}" ,Thread.currentThread().isDaemon());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) throws InterruptedException {
        DaemonThread daemonThread = new DaemonThread();
        daemonThread.setDaemon(true);
        daemonThread.start();
    }
}

Creating a daemon thread is as simple as setting its daemon property to true after creation.

Note that setDaemon(true) must be executed before thread start(), otherwise it will throw an IllegalThreadStateException!

The above example will exit immediately.

If we remove daemonThread.setDaemon(true);, then the JVM will keep running without exiting because the user thread keeps executing.

This is the case if we run in main, what happens if we run in a @Test?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class DaemonThread extends Thread{

    public void run(){
        while(true){
            log.info("Thread A run");
            try {
                log.info("Thread A is daemon {}" ,Thread.currentThread().isDaemon());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testDaemon() throws InterruptedException {
        DaemonThread daemonThread = new DaemonThread();
        daemonThread.start();
    }
}

We have changed the main method to @Test execution. After execution we will see that Test will end immediately, whether it is a daemon thread or not.

Look at the case where a user thread is started in a daemon thread again.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class DaemonBThread extends Thread{

    Thread worker = new Thread(()->{
        while(true){
            log.info("Thread B run");
            log.info("Thread B is daemon {}",Thread.currentThread().isDaemon());
        }
    });
    public void run(){
            log.info("Thread A run");
            worker.start();
    }

    public static void main(String[] args) {
        DaemonBThread daemonThread = new DaemonBThread();
        daemonThread.setDaemon(true);
        daemonThread.start();
    }
}

In this example, daemonThread starts a user thread, and after running it we will see that the JVM will end execution immediately even if a user thread is running.