There are two types of threads in the Java language: user threads and daemon threads, and the difference between the two is relatively unknown, so in this article, I’ll take a look at the differences between the two and what to do about daemon threads.

1. Default user thread

In the Java language, both threads and thread pools default to user threads, so user threads are also called common threads.

For example, if you want to check whether a thread is a daemon thread, you just need to call the isDaemon() method to query. If the value of the query is false, it is not a daemon thread, so it belongs to the user thread.

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run(a) {
            System.out.println("I'm a child thread."); }}); System.out.println("Child thread == daemon thread:" + thread.isDaemon());
    System.out.println("Main thread == daemon thread:" + Thread.currentThread().isDaemon());
}
Copy the code

The execution results of the above procedures are:As can be seen from the above results,By default, both the main thread and the new threads created are user threads.

PS: thread.currentThread () means to get the instance of the Thread executing the current code.

2. Change the thread to the daemon thread

Daemon threads are also called background threads or service threads. Daemon threads serve user threads. When all user threads in the program finish executing, Daemon threads will also follow the end.

The role of the daemon thread is like a “waiter” and the role of the user thread is like a “customer”. When all the customers are gone, the “server” (daemon thread) has no meaning. So when all the user threads in an application have finished executing, The daemon thread will end with the user thread, regardless of whether it is still working, and the program will end with it.

How do you change the default user thread to a daemon thread?

There are two ways to answer this question. In the case of a thread, you can set setDaemon(true) to change the user thread to a daemon thread. In the case of a thread pool, you need to use the ThreadFactory to make every thread in the pool a daemon thread. So let’s do each of these.

2.1 Setting a thread as a daemon thread

If you are using threads, you can change the thread type to daemon with the setDaemon(true) method, as shown below:

 public static void main(String[] args) throws InterruptedException {
     Thread thread = new Thread(new Runnable() {
         @Override
         public void run(a) {
             System.out.println("I'm a child thread."); }});// Set the child thread to a daemon thread
     thread.setDaemon(true);
     System.out.println("Child thread == daemon thread:" + thread.isDaemon());
     System.out.println("Main thread == daemon thread:" + Thread.currentThread().isDaemon());
 }
Copy the code

The execution results of the above procedures are:

2.2 Setting a thread Pool as a daemon thread

To set a thread pool as a daemon thread, you need to set all threads in the pool as a daemon thread. In this case, you need to use the ThreadFactory to define the thread type of each thread in the pool.

// Create a fixed number of thread pools
ExecutorService threadPool = Executors.newFixedThreadPool(10.new ThreadFactory() {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        // Set the thread to a daemon thread
        t.setDaemon(false);
        returnt; }});Copy the code

As shown in the figure below:As you can see from the figure above, I created 10 daemon threads throughout the program. The other types of thread pool creation are set in a similar wayThreadFactoryUnified Settings, here is not a list.

3. Daemon thread vs. user thread

Now that we can create two different thread types, what’s the difference between the two? Let’s take a look at this using a small example.

Let’s create a thread, set it to a user thread and a daemon thread, execute a for loop in each thread, and print information 10 times. After each print, sleep for 100 milliseconds to watch the results of the program.

3.1 User Threads

The new thread is the user thread by default, so we do not need to do any special processing on the thread. We can execute the for loop (a total of 10 times of information printing, sleep for 100 milliseconds after each printing). The implementation code is as follows:

/** * Author: Java Chinese community */
public class DaemonExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run(a) {
                for (int i = 1; i <= 10; i++) {
                    // Print the I information
                    System.out.println("i:" + i);
                    try {
                        // Sleep for 100 milliseconds
                        Thread.sleep(100);
                    } catch(InterruptedException e) { e.printStackTrace(); }}}});// Start the threadthread.start(); }}Copy the code

The execution results of the above procedures are as follows:As you can see from the above results, the process will normally end after the program has executed 10 prints.

3.2 Daemon Thread

/** * Author: Java Chinese community */
public class DaemonExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run(a) {
                for (int i = 1; i <= 10; i++) {
                    // Print the I information
                    System.out.println("i:" + i);
                    try {
                        // Sleep for 100 milliseconds
                        Thread.sleep(100);
                    } catch(InterruptedException e) { e.printStackTrace(); }}}});// Set to daemon thread
        thread.setDaemon(true);
        // Start the threadthread.start(); }}Copy the code

The execution results of the above procedures are as follows:As you can see from the above results, when a thread is set to a daemon thread, the entire program does not wait for the daemon threadforIt loops 10 times before closing, but when the main thread ends, the daemon thread only executes one loop and then terminates, showing the difference between a daemon thread and a user thread.

3.3 summary

Daemons serve user threads. When all user threads in a program finish executing, the program will end running. When the program finishes running, it does not care whether the daemon thread is running or not.

4. Precautions for the daemon thread

There are three issues with daemon thread usage:

  1. Setting of the daemon threadsetDaemon(true)Must be placed in the threadstart()Before, otherwise the program will report an error.
  2. All child threads created in a daemon thread are daemon threads.
  3. usejojn()Method waits for a thread to finish executing, whether it is a user thread or a daemon thread.

Next, let’s demonstrate each of the above considerations.

4.1 Sequence of setDaemon execution

When we set setDaemon(true) after start(), the code looks like this:

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run(a) {
            for (int i = 1; i <= 10; i++) {
                // Print the I information
                System.out.println("i:" + i + ",isDaemon:" +
                            Thread.currentThread().isDaemon());
                try {
                    // Sleep for 100 milliseconds
                    Thread.sleep(100);
                } catch(InterruptedException e) { e.printStackTrace(); }}}});// Start the thread
    thread.start();
    // Set to daemon thread
    thread.setDaemon(true);
}
Copy the code

The execution results of the above procedures are as follows:As can be seen from the above results, when we willsetDaemon(true)Set in thestart()After that, not only will the execution of the program report an error, but the set daemon thread will not take effect.

4.2 Child threads of the daemon thread

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run(a) {
            Thread thread2 = new Thread(new Runnable() {
                @Override
                public void run(a) {}}); System.out.println("Child thread thread2 isDaemon:"+ thread2.isDaemon()); }});// Set to daemon thread
    thread.setDaemon(true);
    // Start the thread
    thread.start();

    Thread.sleep(1000);
}
Copy the code

The execution results of the above procedures are as follows:As can be seen from the above results,A child thread created in a daemon thread is also a daemon thread by default.

4.3 Join and daemon thread

By default, the program does not wait for the daemon thread to finish executing. When we call the thread’s wait method join(), the result is different from the result in section 3.2.

public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run(a) {
            for (int i = 1; i <= 10; i++) {
                // Print the I information
                System.out.println("i:" + i);
                try {
                    // Sleep for 100 milliseconds
                    Thread.sleep(100);
                } catch(InterruptedException e) { e.printStackTrace(); }}}});// Set to daemon thread
    thread.setDaemon(true);
    // Start the thread
    thread.start();
    // Wait until the thread finishes executing
    thread.join();
    System.out.println("Child thread == daemon thread:" + thread.isDaemon());
    System.out.println("Main thread == daemon thread:" + Thread.currentThread().isDaemon());
}
Copy the code

The execution results of the above procedures are as follows:From the above results we can see that even the daemon thread when invoked in the programjoin()Method, the program still waits for the daemon thread to finish executing before terminating the process.

5. Application scenario of daemon thread

Daemon thread of typical application scenario is garbage collection threads, and, of course, some of the scenes are very suitable for use daemon thread, such as the server health detection function, for a server health detection belongs to the service business of non-core non-mainstream, like this for the main business service business function is very suitable to use daemon thread, When the main business in the program is completed, the service business will be destroyed along with it.

6. Execution priority of the daemon thread

First of all, the type of thread (user or daemon) does not affect the priority of the execution of the thread. As shown in the following code, define a user thread and a daemon thread, each execute 100,000 cycles, and observe the final print to determine the effect of the thread type on the priority of the execution of the program.

public class DaemonExample {
    private static final int count = 100000;
    public static void main(String[] args) throws InterruptedException {
        // Define the task
        Runnable runnable = new Runnable() {
            @Override
            public void run(a) {
                for (int i = 0; i < count; i++) {
                    System.out.println(Thread of execution:+ Thread.currentThread().getName()); }}};// Create daemon thread t1
        Thread t1 = new Thread(runnable, "t1");
        // Set to daemon thread
        t1.setDaemon(true);
        // Start the thread
        t1.start();
        // Create user thread t2
        Thread t2 = new Thread(runnable, "t2");
        // Start the threadt2.start(); }}Copy the code

The execution results of the above procedures are as follows:As we can see from the above results, the type of thread, whether it is a daemon or a user thread, has no effect on the priority of the program executiont2When the priority of is adjusted to the maximum, the result of the entire program is completely different, as shown in the following code:

public class DaemonExample {
    private static final int count = 100000;
    public static void main(String[] args) throws InterruptedException {
        // Define the task
        Runnable runnable = new Runnable() {
            @Override
            public void run(a) {
                for (int i = 0; i < count; i++) {
                    System.out.println(Thread of execution:+ Thread.currentThread().getName()); }}};// Create daemon thread t1
        Thread t1 = new Thread(runnable, "t1");
        // Set to daemon thread
        t1.setDaemon(true);
        // Start the thread
        t1.start();
        // Create user thread t2
        Thread t2 = new Thread(runnable, "t2");
        // Set t2 to the highest priority
        t2.setPriority(Thread.MAX_PRIORITY);
        // Start the threadt2.start(); }}Copy the code

The execution results of the above procedures are as follows:By the results of the above, you can see that the type of program and program execution priority is no relationship, when the newly created thread when the default priority is 5, whether it be a daemon thread or user threads, they perform the priorities are the same, when will be the priority setting is not at the same time, the result of the execution will change too, the higher the priority setting, The higher the probability of being executed first).

7. To summarize

In the Java language, threads are divided into user threads and daemon threads. The daemon thread is used to serve the user thread. When all user threads in a program finish, the daemon thread will finish with the user thread regardless of whether it is working. Daemons have low weight from a business logic level, but to the thread scheduler, both daemons and user threads have the same probability of being executed with the same priority. The classic usage scenario for daemons is garbage collection threads, and threads created in daemons are also daemons by default.

Check out the Java Chinese Community for more interesting and informative concurrent programming articles.