Table of Contents
1. Default user thread
2. Actively modify it to a daemon thread
2.1 Set the thread as a daemon thread
2.2 Set the thread pool as a daemon thread
3. Daemon thread VS user thread
3.1 User thread
3.2 Daemon thread
3.3 小结
4.守护线程注意事项
4.1 setDaemon 执行顺序
4.2 守护线程的子线程
4.3 join 与守护线程
5.守护线程应用场景
6.守护线程的执行优先级
Home Java javaTutorial How to use user threads and daemon threads in Java

How to use user threads and daemon threads in Java

May 13, 2023 am 11:28 AM
java

    1. Default user thread

    In the Java language, whether it is a thread or a thread pool, the default is the user thread, so the user Threads are also called ordinary threads.

    Take threads as an example. If you want to check whether a thread is a daemon thread, you only need to query by calling the isDaemon() method. If the query value is false then It means that it is not a daemon thread, so it naturally belongs to the user thread.

    The following code is shown:

    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());
    }
    Copy after login

    The execution result of the above program is:

    How to use user threads and daemon threads in Java

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

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

    2. Actively modify it to a daemon thread

    Daemon thread (Daemon Thread) is also called a background thread or service thread. Daemon thread serves user threads , when all user threads in the program end, the daemon thread will also 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" leave (all execution ends), the "waiter" (daemon thread) also There is no meaning of existence, so when all user threads in a program end execution, no matter whether the daemon thread is still working or not, it will end along with the user threads, and the entire program will also end running.

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

    This question should be answered in two situations. First, if it is a thread, you can directly modify the user thread to a daemon thread by setting the setDaemon(true) method, and If it is a thread pool, you need to use ThreadFactory to make each thread in the thread pool a daemon thread. Next, we will implement it separately.

    2.1 Set the thread as a daemon thread

    If you are using a thread, you can change the thread type to a daemon thread through the setDaemon(true) method, The following code Shown:

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

    The execution result of the above program is:

    How to use user threads and daemon threads in Java

    2.2 Set the thread pool as a daemon thread

    It is relatively troublesome to set the thread pool as a daemon thread. All threads in the thread pool need to be set as daemon threads. At this time, you need to use ThreadFactory to define each thread in the thread pool. The thread type of each thread is determined. The specific implementation code is as follows:

    // 创建固定个数的线程池
    ExecutorService threadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            // 设置线程为守护线程
            t.setDaemon(false);
            return t;
        }
    });
    Copy after login

    As shown in the figure below:

    How to use user threads and daemon threads in Java

    As shown in the figure above, As you can see, there are 10 daemon threads in the entire program created by me. Several other settings for creating thread pools are similar, and they are all set uniformly through ThreadFactory, so I will not list them one by one here.

    3. Daemon thread VS user thread

    Through the previous learning, we can create two different thread types. So what is the difference between the two? Next let's take a look using a small example.

    Next we create a thread, set this thread as a user thread and a daemon thread respectively, execute a for loop in each thread, and print information 10 times in total, each time Then sleep for 100 milliseconds to observe the running results of the program.

    3.1 User thread

    The newly created thread is the user thread by default, so we do not need to perform any special processing on the thread, just execute the for loop (executed 10 times in total Information printing, sleeping for 100 milliseconds after each printing), The implementation code is as follows:

    /**
     * Author:Java中文社群
     */
    public class DaemonExample {
        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++) {
                        // 打印 i 信息
                        System.out.println("i:" + i);
                        try {
                            // 休眠 100 毫秒
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            // 启动线程
            thread.start();
        }
    }
    Copy after login

    The execution results of the above program are as follows:

    How to use user threads and daemon threads in Java

    It can be seen from the above results that the process will not end normally until the program has executed 10 prints.

    3.2 Daemon thread

    /**
     * Author:Java中文社群
     */
    public class DaemonExample {
        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++) {
                        // 打印 i 信息
                        System.out.println("i:" + i);
                        try {
                            // 休眠 100 毫秒
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            // 设置为守护线程
            thread.setDaemon(true);
            // 启动线程
            thread.start();
        }
    }
    Copy after login

    The above program execution results are as follows:

    How to use user threads and daemon threads in Java

    As can be seen from the above results, When the thread is set as a daemon thread, the entire program will not wait for the daemon thread for to cycle 10 times before closing. Instead, when the main thread ends, the daemon thread only executes the cycle once and ends. This shows the difference between daemon threads and user threads.

    3.3 小结

    守护线程是为用户线程服务的,当一个程序中的所有用户线程都执行完成之后程序就会结束运行,程序结束运行时不会管守护线程是否正在运行,由此我们可以看出守护线程在 Java 体系中权重是比较低的。

    4.守护线程注意事项

    守护线程的使用需要注意以下三个问题:

    • 守护线程的设置 setDaemon(true) 必须要放在线程的 start() 之前,否则程序会报错。

    • 在守护线程中创建的所有子线程都是守护线程。

    • 使用 jojn() 方法会等待一个线程执行完,无论此线程是用户线程还是守护线程。

    接下来我们分别演示一下,以上的注意事项。

    4.1 setDaemon 执行顺序

    当我们将 setDaemon(true) 设置在 start() 之后,如下代码所示:

    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++) {
                    // 打印 i 信息
                    System.out.println("i:" + i + ",isDaemon:" +
                                Thread.currentThread().isDaemon());
                    try {
                        // 休眠 100 毫秒
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 启动线程
        thread.start();
        // 设置为守护线程
        thread.setDaemon(true);
    }
    Copy after login

    以上程序执行结果如下:

    How to use user threads and daemon threads in Java

    从上述结果可以看出,当我们将 setDaemon(true) 设置在 start() 之后,不但程序的执行会报错,而且设置的守护线程也不会生效。

    4.2 守护线程的子线程

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Thread thread2 = new Thread(new Runnable() {
                    @Override
                    public void run() {
    
                    }
                });
                System.out.println("守护线程的子线程 thread2 isDaemon:" +
                                  thread2.isDaemon());
            }
        });
        // 设置为守护线程
        thread.setDaemon(true);
        // 启动线程
        thread.start();
    
        Thread.sleep(1000);
    }
    Copy after login

    以上程序执行结果如下:

    How to use user threads and daemon threads in Java

    从上述结果可以看出,守护线程中创建的子线程,默认情况下也属于守护线程

    4.3 join 与守护线程

    通过 3.2 部分的内容我们可以看出,默认情况下程序结束并不会等待守护线程执行完,而当我们调用线程的等待方法 join() 时,执行的结果就会和 3.2 的结果有所不同,下面我们一起来看吧,

    示例代码如下:

    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++) {
                    // 打印 i 信息
                    System.out.println("i:" + i);
                    try {
                        // 休眠 100 毫秒
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        // 设置为守护线程
        thread.setDaemon(true);
        // 启动线程
        thread.start();
        // 等待线程执行完
        thread.join();
        System.out.println("子线程==守护线程:" + thread.isDaemon());
        System.out.println("主线程==守护线程:" + Thread.currentThread().isDaemon());
    }
    Copy after login

    以上程序执行结果如下:

    How to use user threads and daemon threads in Java

    通过上述结果我们可以看出,即使是守护线程,当程序中调用 join() 方法时,程序依然会等待守护线程执行完成之后再结束进程。

    5.守护线程应用场景

    守护线程的典型应用场景就是垃圾回收线程,当然还有一些场景也非常适合使用守护线程,比如服务器端的健康检测功能,对于一个服务器来说健康检测功能属于非核心非主流的服务业务,像这种为了主要业务服务的业务功能就非常合适使用守护线程,当程序中的主要业务都执行完成之后,服务业务也会跟随者一起销毁。

    6.守护线程的执行优先级

    首先来说,线程的类型(用户线程或守护线程)并不影响线程执行的优先级,如下代码所示,定义一个用户线程和守护线程,分别执行 10 万次循环,通过观察最后的打印结果来确认线程类型对程序执行优先级的影响。

    public class DaemonExample {
        private static final int count = 100000;
        public static void main(String[] args) throws InterruptedException {
            // 定义任务
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < count; i++) {
                        System.out.println("执行线程:" + Thread.currentThread().getName());
                    }
                }
            };
            // 创建守护线程 t1
            Thread t1 = new Thread(runnable, "t1");
            // 设置为守护线程
            t1.setDaemon(true);
            // 启动线程
            t1.start();
            // 创建用户线程 t2
            Thread t2 = new Thread(runnable, "t2");
            // 启动线程
            t2.start();
        }
    }
    Copy after login

    以上程序执行结果如下:

    How to use user threads and daemon threads in Java

    通过上述结果可以看出,线程的类型不管是守护线程还是用户线程对程序执行的优先级是没有任何影响的,而当我们将 t2 的优先级调整为最大时,整个程序的运行结果就完全不同了,

    如下代码所示:

    public class DaemonExample {
        private static final int count = 100000;
        public static void main(String[] args) throws InterruptedException {
            // 定义任务
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < count; i++) {
                        System.out.println("执行线程:" + Thread.currentThread().getName());
                    }
                }
            };
            // 创建守护线程 t1
            Thread t1 = new Thread(runnable, "t1");
            // 设置为守护线程
            t1.setDaemon(true);
            // 启动线程
            t1.start();
            // 创建用户线程 t2
            Thread t2 = new Thread(runnable, "t2");
            // 设置 t2 的优先级为最高
            t2.setPriority(Thread.MAX_PRIORITY);
            // 启动线程
            t2.start();
        }
    }
    Copy after login

    以上程序执行结果如下: 

    How to use user threads and daemon threads in Java

    00000000 通过上述的结果可以看出,程序的类型和程序执行的优先级是没有任何关系,当新创建的线程默认的优先级都是 5 时,无论是守护线程还是用户线程,它们执行的优先级都是相同的,当将二者的优先级设置不同时,执行的结果也会随之改变(优先级设置的越高,最早被执行的概率也越大)。

    The above is the detailed content of How to use user threads and daemon threads in Java. For more information, please follow other related articles on the PHP Chinese website!

    Statement of this Website
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

    Hot AI Tools

    Undresser.AI Undress

    Undresser.AI Undress

    AI-powered app for creating realistic nude photos

    AI Clothes Remover

    AI Clothes Remover

    Online AI tool for removing clothes from photos.

    Undress AI Tool

    Undress AI Tool

    Undress images for free

    Clothoff.io

    Clothoff.io

    AI clothes remover

    Video Face Swap

    Video Face Swap

    Swap faces in any video effortlessly with our completely free AI face swap tool!

    Hot Tools

    Notepad++7.3.1

    Notepad++7.3.1

    Easy-to-use and free code editor

    SublimeText3 Chinese version

    SublimeText3 Chinese version

    Chinese version, very easy to use

    Zend Studio 13.0.1

    Zend Studio 13.0.1

    Powerful PHP integrated development environment

    Dreamweaver CS6

    Dreamweaver CS6

    Visual web development tools

    SublimeText3 Mac version

    SublimeText3 Mac version

    God-level code editing software (SublimeText3)

    Perfect Number in Java Perfect Number in Java Aug 30, 2024 pm 04:28 PM

    Guide to Perfect Number in Java. Here we discuss the Definition, How to check Perfect number in Java?, examples with code implementation.

    Weka in Java Weka in Java Aug 30, 2024 pm 04:28 PM

    Guide to Weka in Java. Here we discuss the Introduction, how to use weka java, the type of platform, and advantages with examples.

    Smith Number in Java Smith Number in Java Aug 30, 2024 pm 04:28 PM

    Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

    Java Spring Interview Questions Java Spring Interview Questions Aug 30, 2024 pm 04:29 PM

    In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

    Break or return from Java 8 stream forEach? Break or return from Java 8 stream forEach? Feb 07, 2025 pm 12:09 PM

    Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

    TimeStamp to Date in Java TimeStamp to Date in Java Aug 30, 2024 pm 04:28 PM

    Guide to TimeStamp to Date in Java. Here we also discuss the introduction and how to convert timestamp to date in java along with examples.

    Java Program to Find the Volume of Capsule Java Program to Find the Volume of Capsule Feb 07, 2025 am 11:37 AM

    Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

    Create the Future: Java Programming for Absolute Beginners Create the Future: Java Programming for Absolute Beginners Oct 13, 2024 pm 01:32 PM

    Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.

    See all articles