美文网首页Java
java 并发 守护线程

java 并发 守护线程

作者: 静享时光 | 来源:发表于2020-05-09 00:14 被阅读0次

    后台线程也叫守护线程。可以在调用start开启线程之前,调用setDaemon(true)把线程设置为守护线程。
    注意事项:
    1、main线程不能设置为守护线程,切记。
    2、设置守护线程必须要调用start()方法之前。

    开启守护线程的基本用法

    class SimpleDaemons5 implements Runnable {
    
        private int count = 10;
    
        @Override
        public void run() {
            while (count-- < 0) {
                PrintUtils.print(Thread.currentThread() + " " + this);
            }
        }
    }
    
    public class ThreadTest5 {
        public static void main(String[] args) {
            Thread daemon = new Thread(new SimpleDaemons5());
            //设置守护线程
            daemon.setDaemon(true);
        }
    }
    

    守护线程和非守护线程之间的联系

    main线程和非守护线程之间的联系

    main线程结束,非守护线程。我们看看下面的实例以及打印的结果就可以很清晰的看出来。

    class SimpleDaemons5 implements Runnable {
    
        @Override
        public void run() {
            try {
                while (true) {
                    TimeUnit.MILLISECONDS.sleep(170);
                    PrintUtils.print(Thread.currentThread() + " " + this);
                }
            } catch (InterruptedException e) {
                PrintUtils.print("Sleep interrupterd");
            }
        }
    }
    
    public class ThreadTest5 {
        public static void main(String[] args) {
            PrintUtils.print("main 线程开始");
            Thread daemon = new Thread(new SimpleDaemons5());
            daemon.start();
            try {
                TimeUnit.MILLISECONDS.sleep(175);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            PrintUtils.print("main 线程  结束");
    
    
            /**
             *
             *
             * 输出:
             * main 线程开始
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * main 线程  结束
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * ......
             *
             */
        }
    }
    

    mian线程休息175毫秒之后停止,子线程休息170毫米之后停止,所以子线程有时间能打印结果。

    由输出结果可以看出,当mian线程结束之后,非守护线程依然可以运行。

    非守护线程和守护线程之间的联系

    mian线程+一个守护线程的情况

    main线程也是非守护线程。我们首先看只有一个main线程和一个守护线程的情况

    class SimpleDaemons5 implements Runnable {
    
        @Override
        public void run() {
            try {
                while (true) {
                    TimeUnit.MILLISECONDS.sleep(20);
                    PrintUtils.print(Thread.currentThread() + " " + this);
                }
            } catch (InterruptedException e) {
                PrintUtils.print("Sleep interrupterd");
            }
        }
    }
    
    public class ThreadTest5 {
        public static void main(String[] args) {
            PrintUtils.print("main 线程开始");
            Thread daemon = new Thread(new SimpleDaemons5());
    //设置守护线程
            daemon.setDaemon(true);
            daemon.start();
            try {
                TimeUnit.MILLISECONDS.sleep(175);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            PrintUtils.print("main 线程  结束");
    
    
            /**
             *
             *
             * 输出:
             * main 线程开始
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons5@1d296048
             * main 线程  结束
             *
             * Process finished with exit code 0
             *
             */
        }
    }
    

    示例分析:
    mian线程休息175毫秒之后停止,子线程休息20毫米之后停止,所以子线程有时间能打印结果。
    由输出可以看出,当main线程结束时,守护线程也结束了。

    多个非守护线程+一个守护线程

    我们再来看看有两个非守护线程(其中包括一个mian线程),一个守护线程的情况

    class SimpleDaemons implements Runnable {
    
        @Override
        public void run() {
            try {
                while (true) {
                    TimeUnit.MILLISECONDS.sleep(40);
                    PrintUtils.print("守护正在运行" + Thread.currentThread() + " " + this);
                }
            } catch (InterruptedException e) {
                PrintUtils.print("Sleep interrupterd");
            }
        }
    }
    
    class SimpleDaemons2 implements Runnable {
        private int count = 7;
    
        @Override
        public void run() {
            try {
                while (count-- > 0) {
                    TimeUnit.MILLISECONDS.sleep(40);
                    PrintUtils.print("非守护正在运行  count: " + count);
                }
            } catch (InterruptedException e) {
                PrintUtils.print("Sleep interrupterd");
            }
        }
    }
    
    public class ThreadTest4 {
        public static void main(String[] args) {
            PrintUtils.print("main 线程开始");
    
            //开启守护线程
            Thread daemon = new Thread(new SimpleDaemons());
            //设置为后台线程
            daemon.setDaemon(true);
            daemon.start();
    
            //开启非守护线程
            Thread daemon2 = new Thread(new SimpleDaemons2());
            daemon2.start();
    
            //主线程休息175秒之后结束
            try {
                TimeUnit.MILLISECONDS.sleep(175);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            PrintUtils.print("main 线程  结束");
    
            /**
             * 输出:
             *
             * main 线程开始
             * 非守护正在运行  count: 6
             * 守护正在运行Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons@11f3ef5e
             * 非守护正在运行  count: 5
             * 守护正在运行Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons@11f3ef5e
             * 守护正在运行Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons@11f3ef5e
             * 非守护正在运行  count: 4
             * 非守护正在运行  count: 3
             * 守护正在运行Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons@11f3ef5e
             * main 线程  结束
             * 非守护正在运行  count: 2
             * 守护正在运行Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons@11f3ef5e
             * 守护正在运行Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons@11f3ef5e
             * 非守护正在运行  count: 1
             * 守护正在运行Thread[Thread-0,5,main] annotation_demo.thread_demo.SimpleDaemons@11f3ef5e
             * 非守护正在运行  count: 0
             *
             * Process finished with exit code 0
             *
             */
        }
    }
    

    由输出结果可以看到,main线程结束了,非守护线程没有结束,守护线程也没有结束;
    当非守护线程结束之后,守护线程就结束了。

    综合上面的两个例子,我们可以得出结论:
    只要有任何一个非守护线程(main也是非守护线程)没有结束,守护线程就不会结束;
    如果全部的非守护线程都结束,守护线程就结束。
    可以简单理解为:没有被守护者了,守护者就没有什么意义了。

    相关文章

      网友评论

        本文标题:java 并发 守护线程

        本文链接:https://www.haomeiwen.com/subject/dbbcnhtx.html