Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。
主线程结束了,子线程是否可以正常运行
在面试交流群中,群友遇到了一个面试问题。
Q:主线程结束了,子线程是否可以正常运行?
在 Java 中,主线程结束后子线程是否继续运行取决于子线程的类型,线程分为守护线程(Daemon Thread)和用户线程(User Thread)。
用户线程(User Thread)
如果子线程是用户线程(User Thread)(即没有被设置为守护线程),用户线程则不依赖创建它的线程,那么当主线程结束时,子线程会继续运行,直到它们自然结束或被显式终止。
主线程与子线程是完全独立的生命周期,主线程的结束不会影响到子线程的执行状态。
以下是一个简单的例子,演示了用户线程在主线程结束后继续运行的情况:
public class MainThreadEndsExample {
public static void main(String[] args) {
Thread userThread = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
System.out.println("用户线程运行: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
userThread.start();
try {
Thread.sleep(2000); // 让子线程有时间运行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程结束");
}
}
在这个例子中,主线程在 2 秒后结束,用户线程仍然会继续运行直到完成它的任务
守护线程
守护线程的设计初衷是为了节省资源,通常用于执行一些后台任务,如垃圾回收、监控等。
可以通过 setDaemon(true)
方法,将线程设置为守护线程,但需要注意的是,设置守护线程必须在线程启动之前进行,否则会抛出 IllegalThreadStateException
异常。
如果子线程被设置为守护线程,那么当主线程结束时,如果 JVM 中,还有其他的用户线程,JVM 将等待这些用户线程结束,在这个过程中,守护线程将继续执行,直到所有用户线程结束,守护线程也会自动结束,JVM 也会退出。
以下是一个简单的例子,演示了守护线程和用户线程的行为:
public class DaemonThreadExample {
public static void main(String[] args) {
// 创建并启动一个守护线程
Thread daemonThread = new Thread(() -> {
System.out.println("守护线程启动");
try {
while (true) {
// 模拟后台任务
System.out.println("守护线程运行中");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("守护线程被中断");
}
});
daemonThread.setDaemon(true); // 设置为守护线程
daemonThread.start();
// 创建并启动一个用户线程
Thread userThread = new Thread(() -> {
System.out.println("用户线程启动");
try {
for (int i = 0; i < 5; i++) {
System.out.println("用户线程运行: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("用户线程被中断");
}
System.out.println("用户线程结束");
});
userThread.start();
// 主线程立即结束
System.out.println("主线程结束");
}
}
在这个例子中,尽管主线程很快结束,守护线程和用户线程都继续运行。用户线程在完成其任务后结束,随后守护线程也被中断和终止,JVM随之退出。这表明守护线程不会阻止JVM退出,它们会在所有用户线程结束后自动终止。
Q:主线程结束了,子线程是否可以正常运行
在 Java 中,默认情况下,主线程结束了,如果子线程是用户线程还会继续运行。
如果子线程都是守护线程,那么当主线程结束时,没有其它的用户线程,守护线程也会自动结束,JVM 也会退出。
但如果子线程中有用户线程,那么即使主线程结束了,用户线程仍会继续执行,直到所有的用户线程执行完毕,程序才会完全结束。
Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。