4

面试准备不充分,被Java守护线程干懵了,面试官主打一个东西没用但你得会 - JavaBuild

 6 months ago
source link: https://www.cnblogs.com/JavaBuild/p/18062883
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

面试官:小伙子请聊一聊Java中的精灵线程?
我:什么?精灵线程?啥时候精灵线程?
面试官:精灵线程没听过?那守护线程呢?
我:守护线程知道,就是为普通线程服务的线程嘛。
面试官:没了?守护线程的特点,怎么使用,需要注意啥,Java中经典的守护线程都有啥?
我:不知道。。。
这的天,面试一个10K的工作,上来先整个精灵线程,直接把人整蒙了,难道提及Java多线程的时候,问的不应该是线程、线程池、并发冲突解决方案、如何加锁,以及各种锁的知识点吗?上来整个偏门的守护线程,这是出心的不想要啊。

何为守护线程

上面这段内容是在牛客上看到的,说实话这位面试官问的这内容确实主要一个:东西没用,但你得知道!可如果说他问的真是离谱吗?也算不上,精灵线程我们很少听到,但守护线程我们在学习Java线程的时候肯定有所耳闻!那么今天我们就一起来小酌一下这个 守护线程

Java中的线程分为2种:用户线程守护线程

用户线程又叫普通线程,是我们驱动业务逻辑运转的核心;而守护线程,顾名思义,是守护用户线程的一种线程,运行在后台提供通用服务,因此也叫后台线程或者精灵线程。

守护线程的使用场景

那在Java中这个守护线程都有什么实际用处,或者说应用场景呢?

  1. GC垃圾回收线程:这是JVM中非常经典的一个守护线程,它始终以低级别状态运行,用于实时监控和管理系统中的可回收资源,一旦我们的系统没有任何运行的用户线程时,程序也就不会再产生垃圾,这时,无事可做的垃圾回收线程会自动结束。
  2. 应用指标统计:部分服务可以通过守护线程来采取应用指标,服务结束则停止采集。

怎么设置守护线程

那我们在代码中,如何将一个线程设置为守护线程呢?咱们可以通过在 start 线程之前调用线程的 setDaemon(true) 方法,将一个线程设置为守护线程,来看一下下面的这个demo。

【代码实例1】

public class Test { public static void main(String[] args) { Thread thread1 = new Thread("守护线程"){ @Override public void run() { int i = 0; while (i <= 4){ i++; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+i); } super.run(); } }; Thread thread2 = new Thread("用户线程"){ @Override public void run() { int i = 0; while (i < 2){ i++; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+i); } super.run(); } }; //setDaemon, 不设置则默认false thread1.setDaemon(true);//设置thread1为守护线程 thread2.setDaemon(false);//设置thread2为普通线程 thread1.start(); thread2.start(); }}

输出:

守护线程:1用户线程:1用户线程:2守护线程:2

这段测试代码中,我们通过thread1.setDaemon(true)将线程1设置成了一个守护线程(false为普通线程),用户线程的循环次数为2,用户线程的循环次数为4,但当程序中的用户线程运行完之后,守护线程并没有继续向下循环,而是随着用户线程的结束而自我终止了。

守护线程的优先级

看到网上很多博文提到了守护线程的优先级问题,都说守护线程的优先级比较低,那我们通过一段测试用例看一下真实情况。

【代码实例2】

public class Test { public static void main(String[] args) { Thread thread1 = new Thread("守护线程"){ @Override public void run() { int i = 0; while (i <= 4){ i++; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+i+"-优先级:" +Thread.currentThread().getPriority()); } super.run(); } }; Thread thread2 = new Thread("用户线程"){ @Override public void run() { int i = 0; while (i < 2){ i++; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":"+i+"-优先级:" +Thread.currentThread().getPriority()); } super.run(); } }; //setDaemon, 不设置则默认false thread1.setDaemon(true);//设置thread1为守护线程 thread2.setDaemon(false);//设置thread2为普通线程 thread1.start(); thread2.start(); for (int i = 0; i <5 ; i++) { System.out.println("主线程:"+i+"-优先级:" +Thread.currentThread().getPriority()); } }}

输出:

主线程:0-优先级:5主线程:1-优先级:5主线程:2-优先级:5主线程:3-优先级:5主线程:4-优先级:5用户线程:1-优先级:5守护线程:1-优先级:5用户线程:2-优先级:5守护线程:2-优先级:5

这个测试结果是不是出乎意料?无论是主线程还是普通的用户线程,又或者说守护线程,他们的优先级都是5,优先级竟然都一样!

我们知道所谓的线程就是CPU 调度和分派的基本单位,根据优先级不同,来决定获取CPU时间片的先后顺序,因为主线程启动时,其他线程还没有启动,所以这时候它最先获得CPU调度权限;

又因为其他线程存在休眠时间,这个时间段上足够主线程执行完毕。主线程执行完后,用户线程和守护线程互相抢占CPU资源,交错执行,直至程序中没有普通线程为止!若没有休眠时间,且循环次数足够多时,我们可以看到主线程、守护线程、用户线程都竞争CPU时间片,呈现交错执行的结果!

在设置线程为守护线程的时候要注意一个事情,那就是当 start(); 放到 setDaemon(true); 之前,程序抛出IllegalThreadStateException。如下图:

image

原因是 setDaemon(true)源码中,有一个isAlive()的判断,判断当前线程的状态是否为活跃线程,若是则抛出异常,我们不能修改一个正在运行中的线程!

【源码解析1】

public final void setDaemon(boolean on) { checkAccess(); //线程已经启动后,不可修改,否则抛出非法线程状态异常 if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; }

OK,写到这里,关于守护线程的内容就讲完了,我们从什么是守护线程,守护线程的使用场景,优先级,注意事项等方面,进行了全面的介绍。

其实说实话,在我们日后工作中,很少直接使用上守护线程,所以它看似没那么重要,但在很多Java多线程相关的书籍中绝对都有提及,很多小伙伴在学习的过程中认为这个点不重要,也就相当然的忽略了,但遇到变态的面试官,专门挑拣一些偏僻的知识点考你时,难免陷入尴尬,所以希望借助这个考题,大家能够在日后更细心的学习哈。

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

image

如果您想与Build哥的关系更近一步,还可以关注“JavaBuild888”,在这里除了看到《Java成长计划》系列博文,还有提升工作效率的小笔记、读书心得、大厂面经、人生感悟等等,欢迎您的加入!

image


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK