回答
在 Java 语言中,线程分为两类:
- 用户线程(User Thread)
- 守护线程(Deamon Threa)
一般情况下,如果不做特殊配置,我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程,它一般用于执行用户级任务。
而守护线程则是一种比较特殊的线程,它一般都是为其他的线程服务,在后台默认完成一些系统服务,比如垃圾回收线程就是一个典型的守护线程。
守护线程和普通线程的区别有这么几点:
- 退出机制:普通线程会阻止 JVM 的退出,直到所有的普通线程执行完毕。而守护线程不会阻止 JVM 的退出。守护线程是为用户线程服务的,当一个应用中的所有用户线程都执行完成之后,应用程序也会结束运行,应用程序结束运行时是不会管守护线程是否正在运行。
- 用途和重要性:普通线程通常用于执行应用程序的核心功能,而守护线程则用于服务,比如资源管理或者监控之类的。
扩展知识
我们可以调用 setDaemon(true) 来设置某个线程为守护线程,但是它必须要放在线程的 start()
之前,否则程序会报错。
public class DaemonThreadTest {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(() ->{
System.out.println("我是大明哥,这是大明哥的 Java 面试题 600 讲!!!");
});
thread.start();
thread.setDaemon(true);
}
}
执行结果:
Exception in thread "main" java.lang.IllegalThreadStateException
at java.base/java.lang.Thread.setDaemon(Thread.java:2239)
at com.skjava.java.feature.DaemonThreadTest.main(DaemonThreadTest.java:10)
调用 isDaemon()
可以判断某个线程是否为守护线程:
public class DaemonThreadTest {
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(() ->{
System.out.println("我是大明哥,这是大明哥的 Java 面试题 600 讲!!!");
});
Thread thread2 = new Thread(() ->{
System.out.println("我是大明哥,这是大明哥的 Java 面试题 600 讲!!!");
});
thread1.setDaemon(true);
System.out.println("thread1 是否为守护线程:" + thread1.isDaemon());
System.out.println("thread2 是否为守护线程:" + thread2.isDaemon());
}
}
执行结果:
thread1 是否为守护线程:true
thread2 是否为守护线程:false
大明哥在上面提过,当应用程序中只剩下守护线程时,JVM 就会退出:
public class DaemonThreadTest {
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(() ->{
for (int i = 1 ; i <= 10 ; i++) {
System.out.println("我是守护线程,运行 " + i + "次..");
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread1.setDaemon(true);
Thread thread2 = new Thread(() ->{
for (int i = 1 ; i <= 10 ; i++) {
System.out.println("我是普通线程,运行 " + i + "次..");
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread1.start();
thread2.start();
}
}
普通线程 for 循环 10 次,每次等待 100 毫秒,而守护线程 for 循环 10 次,每次等待 300 毫秒,运行结果如下:
普通线程执行了 10 次,而守护线程只执行了 4 次 JVM 就退出了。
如果我们在守护线程中创建线程呢,该线程是守护线程还是普通线程?
public class DaemonThreadTest {
public static void main(String[] args) throws Exception {
Thread thread1 = new Thread(() ->{
Thread thread2 = new Thread(() -> {
});
System.out.println("thread2 守护线程子线程是守护线程:" + thread2.isDaemon());
});
thread1.setDaemon(true);
thread1.start();
TimeUnit.SECONDS.sleep(2);
}
}
执行结果:
thread2 守护线程子线程是守护线程:true
所以守护线程中创建的子线程,默认情况下也属于守护线程。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。