java - 一个线程中的异常会导致应用程序停止吗?

标签 java

我的应用程序中有六个线程在运行。如果一个线程抛出 StackOverFlow 异常,所有线程或应用程序是否会停止工作?

最佳答案

通常-不,

一个线程中的异常不会杀死另一个线程;

除非……


长一点的故事

Java 中有两种类型的线程:普通线程守护线程,它们的区别仅在于它们退出时发生的情况。

当一个线程退出时,JVM 会执行一个正在运行的线程的 list ,并且

if only daemon threads are left alive

JVM 启动有序关闭(意思是,它在 main 线程完成执行后关闭)。

当 JVM 停止时,任何剩余的守护线程都将被放弃——finally block 不会被执行,堆栈不会被展开——JVM 就退出了。

因此,当您的线程中出现未处理的异常时,可能会出现以下两种情况之一:

  1. JVM 将关闭 - 您的线程是最后一个正常线程,在 JVM 在此线程退出后执行另一次库存检查后,它将关闭,因为没有其他正常线程(概念上) JVM 认为,没有什么重要的东西在运行,因为守护线程永远不应该用于重要/不安全的操作);
  2. 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 引用的普通线程将继续执行。


最后的笔记

  1. 注意,当JVM启动时(Java程序启动),它创建的所有线程(如垃圾收集器和其他管家线程)都是守护线程,主线程除外,它是一个普通线程;但是,如果您创建一个新线程,它会继承创建它的线程的类型;

  2. 我在第一个代码片段中显式设置 .setDaemon(true) 的唯一原因是线程类型继承自创建它的线程。

关于java - 一个线程中的异常会导致应用程序停止吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66784186/

相关文章:

javascript - 文件上传 API 可与 Postman 配合使用,但不能与 AngularJS 配合使用

java - 使用SBT下载jMonkeyEngine

java - 控制 - Java 中的 C 异常

java - 如何使用 sendKeys(Keys.TAB) + sendKeys ("text") 作为联系我们表格

java - 接口(interface)的引用可以= null吗?

java - 一个简单的 Java SOAP 客户端

java - 我们应该在 Java 中保持每行 80 个字符吗?

java - Spring 4 验证不起作用

Java:减去日期的最简单方法

java - Http 基本身份验证在 Spring Security 中不起作用