我的应用程序中有六个线程在运行。如果一个线程抛出 StackOverFlow 异常,所有线程或应用程序是否会停止工作?
最佳答案
通常-不,
一个线程中的异常不会杀死另一个线程;
除非……
长一点的故事
Java 中有两种类型的线程:普通线程 和守护线程,它们的区别仅在于它们退出时发生的情况。
当一个线程退出时,JVM 会执行一个正在运行的线程的 list ,并且
if only daemon threads are left alive
JVM 启动有序关闭(意思是,它在 main
线程完成执行后关闭)。
当 JVM 停止时,任何剩余的守护线程都将被放弃——finally block 不会被执行,堆栈不会被展开——JVM 就退出了。
因此,当您的线程中出现未处理的异常时,可能会出现以下两种情况之一:
- JVM 将关闭 - 您的线程是最后一个正常线程,在 JVM 在此线程退出后执行另一次库存检查后,它将关闭,因为没有其他正常线程(概念上) JVM 认为,没有什么重要的东西在运行,因为守护线程永远不应该用于重要/不安全的操作);
- JVM 将继续运行 - 您的线程不是最后一个正常线程,并且在其中发生未处理的异常后,JVM 将继续运行。
例如,在这种情况下:
public class EntryPoint {
public static void main(String[] args) throws Exception {
Thread t = new Thread(() -> {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
System.out.println("Thread " + Thread.currentThread().getName() + " " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
if (i == 4) {
throw new StackOverflowError("JVM exits in this case.");
}
System.out.println("Call number " + i);
}
}
}
一旦抛出异常,您的应用程序就会崩溃,因为没有正常的线程在运行;
然而,在这种情况下:
public class EntryPoint {
public static void main(String[] args) throws Exception {
Thread t = new Thread(() -> {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
System.out.println("Thread " + Thread.currentThread().getName() + " " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.setDaemon(false);
t.start();
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
if (i == 4) {
throw new StackOverflowError("JVM won't exit in this case.");
}
System.out.println("Call number " + i);
}
}
}
由 t
引用的普通线程将继续执行。
最后的笔记
注意,当JVM启动时(Java程序启动),它创建的所有线程(如垃圾收集器和其他管家线程)都是守护线程,主线程除外,它是一个普通线程;但是,如果您创建一个新线程,它会继承创建它的线程的类型;
我在第一个代码片段中显式设置
.setDaemon(true)
的唯一原因是线程类型继承自创建它的线程。
关于java - 一个线程中的异常会导致应用程序停止吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66784186/