守护线程

每篇一句

把事情变复杂很简单,把事情变简单很复杂。这需要彻底的深入理解!这就是别人强大的原因, 我在路上,我的进步少不了前人的帮助,更加少不了自己的坚持

在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)

一. 用户线程

  • 用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止
  • main主线程可以看成一个特殊的用户线程
  • 只要有一个用户线程没有结束,那么jvm都不会停止.

二. 守护线程

定义: 守护线程是为其他线程服务的线程,最典型的就是cg垃圾回收器

创建守护线程很简单setDaemon(true);方法就行了

Thread thread = new MyThread();
thread.setDaemon(true);
thread.start();
  • 必须注意的是:thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
  • 在Daemon线程中产生的新线程也是守护线程。

三. 守护线程很其他线程的关系

1. 守护线程不影响JVM的停止,JVM退出时,不必关心守护线程是否已结束。
  • 在JVM中,所有非守护线程都执行完毕后,无论有没有守护线程,虚拟机都会自动退出。如果存在一个非守护线程,jvm是不会关闭的

由于以上关系,我们可以推断出以下结论:

  • 守护线程不能持有任何需要关闭的资源,例如打开文件等,因为虚拟机退出时,守护线程没有任何机会来关闭文件,这会导致数据丢失。
2. 那守护线程什么时候关闭呢?
  • 当守护线程没有需要服务的线程的时候,会关闭,
  • 他和JVM没有关系!!!即使JVM退出了守护线程也可能存在, 这一点在很多博客中都误以为守护线程和JVM一同关闭,这是错误的,如果你有幸看到我的博客,又看了别人的博客,发现不一样,那么我可以肯定的告诉你, 他们的错了!

也不能说其他博客说的一点都不对, 因为大多数情况下, JVM关闭了也就意味着, 没有守护线程需要服务的线程了, 自然也就和JVM一同关闭了. 但是站在学术严禁的角度来说, 错就是错!望周知~

说了这么多,其实也一句话总结: 用户线程会影响jvm的关闭, 而守护线程不会影响jvm的关闭

3. Priority与守护线程的关系

有一种传言为守护线程的优先级要低,然而事实是:

  • 优先级与是否为守护线程没有必然的联系
  • 新的线程的优先级与创建该线程的线程优先级一致。
  • 但是建议将守护线程的优先级降低一些。
验证JVM不等待守护线程就会结束

用一段代码验证一下JVM不等待用户启动的守护线程结束就退出的事实。


     private static void testDaemonThread() {
        long startTime = System.currentTimeMillis();
        Thread daemonThreadSetByUser = new Thread("daemonThreadSetByUser") {
            @Override
            public void run() {
                makeThreadSleep(10 * 1000);
                super.run();
                System.out.println("daemonThreadSetByUser.time cost=" + (System.currentTimeMillis() - startTime));
            }
        };
        daemonThreadSetByUser.setDaemon(true);
        daemonThreadSetByUser.start();
        //主线程暂定3秒,确保子线程都启动完成
        makeThreadSleep(3 * 1000);
        dumpAllThreadsInfo();
        System.out.println("MainThread.time cost = " + (System.currentTimeMillis() - startTime));
    }

    private static void dumpAllThreadsInfo() {
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        for(Thread thread: threadSet) {
            System.out.println("dumpAllThreadsInfo thread.name=" + thread.getName()
                    + ";group=" + thread.getThreadGroup()
                    + ";isDaemon=" + thread.isDaemon()
                    + ";priority=" + thread.getPriority());
        }
    }
    private static void makeThreadSleep(long durationInMillSeconds) {
        try {
            Thread.sleep(durationInMillSeconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

输出日志信息:

dumpAllThreadsInfo thread.name=Signal Dispatcher;group=java.lang.ThreadGroup[name=system,maxpri=10];isDaemon=true;priority=9
dumpAllThreadsInfo thread.name=Attach Listener;group=java.lang.ThreadGroup[name=system,maxpri=10];isDaemon=true;priority=9
dumpAllThreadsInfo thread.name=Monitor Ctrl-Break;group=java.lang.ThreadGroup[name=main,maxpri=10];isDaemon=true;priority=5
dumpAllThreadsInfo thread.name=Reference Handler;group=java.lang.ThreadGroup[name=system,maxpri=10];isDaemon=true;priority=10
dumpAllThreadsInfo thread.name=main;group=java.lang.ThreadGroup[name=main,maxpri=10];isDaemon=false;priority=5
dumpAllThreadsInfo thread.name=daemonThreadSetByUser;group=java.lang.ThreadGroup[name=main,maxpri=10];isDaemon=true;priority=5
dumpAllThreadsInfo thread.name=Finalizer;group=java.lang.ThreadGroup[name=system,maxpri=10];isDaemon=true;priority=8
MainThread.time cost = 3006
Process finished with exit code 0

参考资料:
https://www.jb51.net/article/154132.htm
https://www.cnblogs.com/baizhanshi/p/8289202.html
https://segmentfault.com/a/1190000018964390

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值