Daemon后台线程

后台线程(daemon)

所谓后台线程(daemon),是指程序在运行时提供的一种通用线程服务,这种线程并不属于程序中不可或缺的部分。因此,所有的非后台线程结束后,程序也就会终结所有的线程,同时会杀死所有的后台现场。也就是说,程序中只要有后台线程还在运行,那么程序就不会终止。比如,执行main()方法就是一个非后台线程。

public class DaemonThread implements Runnable{
    @Override
    public void run() {
        while (true){
            try {
                TimeUnit.MILLISECONDS.sleep(100);
                System.out.println(Thread.currentThread() +"  " + this);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

    }


    public static void main(String[] args) throws InterruptedException {
        for(int i = 0 ; i< 10 ;i ++ ){
            Thread thread = new Thread(new DaemonThread());
            thread.setDaemon(true);
            thread.start();


        }
        System.out.println("All dacmoi start!");
        TimeUnit.MILLISECONDS.sleep(1000);
    }


}

这里的thread.setDaemon(true);就是把一个线程的daemon属性设置为true,那么系统就会认为她是一个后台线程。当main()方法运行完毕后,就一切终止了,包括后台线程。但是如果在main()方法中最后一句加上sleep让它休眠,那么你就会看到后台线程开始运行。这样就是显式的创建了一个后台线程。

同时可以使用ThreadFactory隐式的创建后台线程。

public class DaemonThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setDaemon(true);
        return thread;
    }

    /**
     * 后台线程,main方法结束后,便马上结束
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newCachedThreadPool(new DaemonThreadFactory());
        for(int i  = 0 ;i < 10;i++){
            service.execute(new DaemoinFromFactory());

        }
        service.shutdown();
        System.out.println("test");
        TimeUnit.MILLISECONDS.sleep(167);
    }

}

DaemonThreadFactory 要使用线程池Executors来配合使用,唯一的差异化就是把你提供的线程都隐式的设置为deaemon=true,每个静态的ExecutorService 都可以接受一个ThreadFactory对象。而这个对象将被默认的创建新的线程。也可以通过isDaemon()判断一个线程是否是一个后台线程

如果一个线程被设置为后台线程,但是它里面派生了很多子线程,那么派生的子线程也会设置为后台线程。

public class DaemonMoney implements Runnable{
    private Thread[] t = new Thread[10];

    @Override
    public void run() {
        for(int i = 0 ;i < 10;i ++){
            t[i] = new Thread(new SpanwThread());
            t[i].start();
            System.out.println("Daemo span " + i + " start !");
        }
        for(int i = 0 ;i < t.length;i ++){
            System.out.println("t{ " + i  + "] .isDamon " + t[i].isDaemon() + " .");

        }

        while (true){
            Thread.yield();

        }
    }


    public static void main(String[] args) throws InterruptedException {
        Thread d = new Thread(new DaemonMoney());
        d.setDaemon(true);
        d.start();

        System.out.println("d.isDeamon  " + d.isDaemon() + " .");
        TimeUnit.MILLISECONDS.sleep(100);


    }


}

class SpanwThread implements Runnable{


    @Override
    public void run() {
        while (true){
            Thread.yield();

        }
    }

}

这里写图片描述

后台线程中若是存在finally()方法,猜会不会执行呢??
这里写图片描述

答案是不会执行,因为即便finally这种行为是正确的,但是情况依然如此,当最后一个后台线程终止时,后台线程会突然终止,因此一旦main()结束,那么所有的线程都将结束。而不会有你的希望出现的确认形式。因此,你不能优雅的关闭所有的后台线程,使用Exectuor是一种更好的方式。

猜你喜欢

转载自blog.csdn.net/Lovincc/article/details/80734035