• java多线程基本概述(十五)——DaemonThread


    所谓守护线程(DaemonThread),是指在程序运行的时候在后台提供的一种通用的服务线程,并且这种线程并不属于程序中不可或缺的一部分。因此,当所有非守护线程(前台线程)都结束时,程序也就终止了。同时会杀死所有的后台线程,反过来说,只要又任何非守护线程还在执行,程序就不会终止,比如main()方法就是一个非守护线程。

    1.

    例子:

    package tij;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by huaox on 2017/4/19.
     */
    public class DaemonTest implements Runnable{
    
        @Override
        public void run() {
            try {
                while (true){
                    TimeUnit.MILLISECONDS.sleep(100);
                    System.out.println(Thread.currentThread()+"  "+this);
                }
            }catch (InterruptedException e){
                System.out.println("sleep() interrupted");
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 10; i++) {
                Thread daemon = new Thread(new DaemonTest());
                daemon.setDaemon(true);//必须再线程启动之前把它设为守护线程,否则无效
                daemon.start();
            }
            System.out.println("All daemon started");
            TimeUnit.MILLISECONDS.sleep(200);//把这行语句可以注释掉查看效果
        }
    }

    输出结果:

    All daemon started
    Thread[Thread-6,5,main]  tij.DaemonTest@3943de20
    Thread[Thread-2,5,main]  tij.DaemonTest@28979470
    Thread[Thread-4,5,main]  tij.DaemonTest@333cafca
    Thread[Thread-3,5,main]  tij.DaemonTest@131c736d
    Thread[Thread-5,5,main]  tij.DaemonTest@362363a6
    Thread[Thread-0,5,main]  tij.DaemonTest@43a3a747
    Thread[Thread-1,5,main]  tij.DaemonTest@4521d907
    Thread[Thread-8,5,main]  tij.DaemonTest@782b1823
    Thread[Thread-7,5,main]  tij.DaemonTest@1bb19ff0
    Thread[Thread-9,5,main]  tij.DaemonTest@4559f79
    
    Process finished with exit code 0

    因为前台线程main()方法,正在休眠,那么另外的十个守护线程才有机会执行。如果注释掉main()线程中的那条休眠语句,那么程序的执行效果如下:

    All daemon started
    
    Process finished with exit code 0

    可以看到程序在main()执行完立即返回了,并没有等待后台线程的执行。

    2.我们也可以通过ThreadFactory来定制有Executor创建的线程的属性(名称,优先级,名称):

    代码如下:

    package tij;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by huaox on 2017/4/19.
     *
     */
    
    class DaemonThreadFactory implements ThreadFactory{
    
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            return thread;
        }
    }
    
    class DaemonFromFactory implements Runnable{
    
        @Override
        public void run() {
            try {
                while (true){
                    TimeUnit.MILLISECONDS.sleep(100);
                    System.out.println(Thread.currentThread()+" "+this);
                }
            } catch (InterruptedException e) {
                System.out.println("interrupted");
            }
        }
    }
    
    public class DaemonTest2 {
        public static void main(String[] args) throws InterruptedException {
            ExecutorService executorService = Executors.newCachedThreadPool(new DaemonThreadFactory());//使用自己的ThreadFactory
            for (int i = 0; i < 10; i++) {
                executorService.execute(new DaemonFromFactory());
            }
            System.out.println("All daemon started");
            TimeUnit.MILLISECONDS.sleep(500);//把这行语句可以注释掉查看效果
        }
    }

    输出结果:

    All daemon started
    Thread[Thread-9,5,main] tij.DaemonFromFactory@b20568f
    Thread[Thread-8,5,main] tij.DaemonFromFactory@3d6741a8
    Thread[Thread-7,5,main] tij.DaemonFromFactory@3d7c301d
    Thread[Thread-5,5,main] tij.DaemonFromFactory@655a2155
    Thread[Thread-6,5,main] tij.DaemonFromFactory@5169ce60
    Thread[Thread-4,5,main] tij.DaemonFromFactory@2cf9cd59
    Thread[Thread-2,5,main] tij.DaemonFromFactory@710a3057
    Thread[Thread-3,5,main] tij.DaemonFromFactory@7f05b150
    Thread[Thread-0,5,main] tij.DaemonFromFactory@47a2a66c
    Thread[Thread-1,5,main] tij.DaemonFromFactory@6f9777db
    Thread[Thread-1,5,main] tij.DaemonFromFactory@6f9777db
    Thread[Thread-0,5,main] tij.DaemonFromFactory@47a2a66c
    Thread[Thread-3,5,main] tij.DaemonFromFactory@7f05b150
    Thread[Thread-2,5,main] tij.DaemonFromFactory@710a3057
    Thread[Thread-4,5,main] tij.DaemonFromFactory@2cf9cd59
    Thread[Thread-6,5,main] tij.DaemonFromFactory@5169ce60
    Thread[Thread-5,5,main] tij.DaemonFromFactory@655a2155
    Thread[Thread-7,5,main] tij.DaemonFromFactory@3d7c301d
    Thread[Thread-8,5,main] tij.DaemonFromFactory@3d6741a8
    Thread[Thread-9,5,main] tij.DaemonFromFactory@b20568f
    Thread[Thread-9,5,main] tij.DaemonFromFactory@b20568f
    Thread[Thread-7,5,main] tij.DaemonFromFactory@3d7c301d
    Thread[Thread-8,5,main] tij.DaemonFromFactory@3d6741a8
    Thread[Thread-4,5,main] tij.DaemonFromFactory@2cf9cd59
    Thread[Thread-6,5,main] tij.DaemonFromFactory@5169ce60
    Thread[Thread-5,5,main] tij.DaemonFromFactory@655a2155
    Thread[Thread-2,5,main] tij.DaemonFromFactory@710a3057
    Thread[Thread-3,5,main] tij.DaemonFromFactory@7f05b150
    Thread[Thread-0,5,main] tij.DaemonFromFactory@47a2a66c
    Thread[Thread-1,5,main] tij.DaemonFromFactory@6f9777db
    Thread[Thread-1,5,main] tij.DaemonFromFactory@6f9777db
    Thread[Thread-3,5,main] tij.DaemonFromFactory@7f05b150
    Thread[Thread-0,5,main] tij.DaemonFromFactory@47a2a66c
    Thread[Thread-2,5,main] tij.DaemonFromFactory@710a3057
    Thread[Thread-5,5,main] tij.DaemonFromFactory@655a2155
    Thread[Thread-6,5,main] tij.DaemonFromFactory@5169ce60
    Thread[Thread-4,5,main] tij.DaemonFromFactory@2cf9cd59
    Thread[Thread-8,5,main] tij.DaemonFromFactory@3d6741a8
    Thread[Thread-7,5,main] tij.DaemonFromFactory@3d7c301d
    Thread[Thread-9,5,main] tij.DaemonFromFactory@b20568f
    
    Process finished with exit code 0

    可以通过调用isDaemon()方法来查看一个先蹭时候属于后台线程,如果时一个后台线程,那么它创建的任何线程都将被自动设置为守护线程。示例如下:

    package tij;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * Created by huaox on 2017/4/19.
     *
     */
    
     class Daemon implements Runnable{
        Thread[] threads = new Thread[10];
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                threads[i] = new Thread(new DaemonSpawn());
                threads[i].start();//这个地方之前并没有给DaemonSpawn这个线程设置为守护线程,但从输出看,它“自动”被设置为守护线程了
                System.out.println("DaemonSpawn "+i+" started "+threads[i].isDaemon());
            }
    
            for (int i = 0; i < 10; i++) {
                System.out.println("threads[ "+i+"].isDaemon() = "+threads[i].isDaemon());
            }
            while (true)
                Thread.yield();
        }
    }
    class DaemonSpawn implements Runnable{
    
        @Override
        public void run() {
            while (true)
                Thread.yield();
        }
    }
    public class DaemonTest3 {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(new Daemon());
            thread.setDaemon(true);
            thread.start();
            System.out.println("thread.isDaemon() = "+thread.isDaemon());
            TimeUnit.SECONDS.sleep(5);//给守护线程一点时间去执行完成
        }
    
    }

    输出结果:

    thread.isDaemon() = true , 
    DaemonSpawn 0 started true
    DaemonSpawn 1 started true
    DaemonSpawn 2 started true
    DaemonSpawn 3 started true
    DaemonSpawn 4 started true
    DaemonSpawn 5 started true
    DaemonSpawn 6 started true
    DaemonSpawn 7 started true
    DaemonSpawn 8 started true
    DaemonSpawn 9 started true
    threads[ 0].isDaemon() = true
    threads[ 1].isDaemon() = true
    threads[ 2].isDaemon() = true
    threads[ 3].isDaemon() = true
    threads[ 4].isDaemon() = true
    threads[ 5].isDaemon() = true
    threads[ 6].isDaemon() = true
    threads[ 7].isDaemon() = true
    threads[ 8].isDaemon() = true
    threads[ 9].isDaemon() = true
    
    Process finished with exit code 0

    从结果可以验证之前的结果。

    3.守护线程的finally不一定执行!!!

    示例如下:

    class Adaemon implements Runnable{
        @Override
        public void run() {
            try {
                System.out.println("Adaemon started");
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                System.out.println("this should always run?");
            }
        }
    }
    
    public class DaemonTest3 {
        public static void main(String[] args) throws InterruptedException{
            Thread thread = new Thread(new Adaemon());
            thread.setDaemon(true);
            thread.start();
            TimeUnit.SECONDS.sleep(1);
        }
    }

    输出结果:

    Adaemon started
    this should always run?
    
    Process finished with exit code 0

    可以看到finally中的自居并不会被执行。当注销设置守护线程的那句代码时会发现finally子句被执行

  • 相关阅读:
    vue路由传参页面刷新参数丢失问题解决方案
    理解MVC,MVP 和 MVVM
    HTTPS用的是对称加密还是非对称加密?
    元素显示隐藏的9种思路
    CSS中层叠上下文
    DOM盒模型和位置 client offset scroll 和滚动的关系
    css重点知识和bug解决方法
    你可能不知道的CSS
    如何在 React 中优雅的写 CSS?
    html5不常用标签应用场景
  • 原文地址:https://www.cnblogs.com/soar-hu/p/6736161.html
Copyright © 2020-2023  润新知