在Java程序的主线程中,调用System.exit(0)和Thread.currentThread().interrupt()有什么区别?

23
两者都会导致程序停止执行。但显然它们在发生的方式上一定存在一些差异,那么这些差异是什么呢?

1
你的前提是错误的。不是一个真正的问题。 - user207421
刚写了一些测试代码;你是对的。 - brandones
3个回答

44

摘要

  1. thread.interrupt() 不会停止线程,它用于多线程程序的协调。除非您确切知道自己在做什么,否则不要使用它。
  2. 抛出 RuntimeException 通常会终止线程,但不一定终止程序。
  3. System.exit(int) 几乎总是终止程序并返回状态码。
  4. 在异常情况下,System.exit(int) 可能无法真正停止程序。相反,Runtime.getRuntime().halt(int) 总是能够停止程序。

线程中断

很抱歉,您的第一句话是错误的。Thread.currentThread().interrupt() 不会停止线程或程序。

中断线程是一种向其发出信号以应该停止的方式,但这是一种合作的努力:线程中的代码应该定期检查已中断的状态,并且(在大多数情况下 - 但即使这也只是可选项)如果被中断应该停止。如果它不这样做,什么也不会发生。

具体来说,中断一个线程(任何线程,包括当前正在执行的线程)只会设置“已中断”标志。标准库中的某些方法将抛出InterruptedException,但这也只是一种信号,表示线程已被中断。在这种情况下应该做什么取决于运行在该线程中的代码。
以下是Brian Goetz的《Java并发编程实战》书中相关部分:
Thread提供了中断方法来中断线程并查询线程是否已被中断。每个线程都有一个布尔属性表示其中断状态;中断线程会设置此状态。
中断是一种合作机制。一个线程不能强制另一个线程停止正在做的事情并做其他事情;当线程A中断线程B时,A只是请求B在方便的停止点停止正在做的事情,如果它觉得需要的话。虽然API或语言规范中没有要求中断的任何特定应用级语义,但中断的最明智用途是取消活动。对中断响应的阻塞方法使及时取消长时间运行的活动更加容易。

异常和System.exit(int)

System.exit(int)的Javadoc说:

终止当前正在运行的Java虚拟机。参数用作状态码;按照惯例,非零状态代码表示异常终止。

因此调用exit()(几乎)肯定会停止您的程序。与抛出RuntimeException(或Error)相比,这不能在调用堆栈的某个位置捕获,并且也不取决于是否有其他线程正在运行。另一方面,未捕获的异常会终止抛出它的线程,但如果存在任何其他(非守护程序)线程,则程序将继续运行。

与抛出异常的另一个区别是,exit()不会向控制台打印任何内容(与未捕获的异常一样),而是使程序返回特定的状态码。状态码有时用于shell或批处理脚本,但除此之外,它们并不是非常有用。

Runtime.halt(int)

为了完整起见,我想指出退出Java程序的第三种可能性。当调用System.exit(int)(或以其他方式结束程序)时,运行时会在Java虚拟机停止之前进行一些清理工作。这在Runtime.exit(int)的Javadoc中有描述(由System.exit(int)调用):

虚拟机的关闭序列包括两个阶段。在第一阶段中,所有已注册的关闭挂钩(如果有)将以某种未指定的顺序启动,并允许并发运行,直到它们完成。在第二阶段中,如果启用了退出时终结,则运行所有未调用的终结器。完成这些操作后,虚拟机就会停止。

如果任何一个关闭挂钩或终结器被阻止完成,例如因为死锁,程序可能永远无法退出。唯一保证JVM停止的方法是Runtime.halt(int)

应该极度谨慎地使用此方法。与exit方法不同,此方法不会启动关闭挂钩,并且如果启用了终止时运行未调用的终结器,则不会运行未调用的终结器。


20

如果还有其他(非守护线程)正在运行,停止主线程不会使JVM退出。System.exit()将终止所有其他线程。


4
你写的是正确的,但与线程中断无关。如果你中断一个线程,它不会只是停止。该线程运行的代码将决定在被中断时发生什么。 - rolve

1
在多线程应用程序中,有多个线程正在执行。 Thread.currentThread().interrupt() 只会中断当前正在执行的线程,但是其余线程将继续运行,即使您的主线程被中断。
System.exit(0) 会导致系统结束。所有线程都将被终止。

3
Thread.currentThread().interrupt() 只会在当前线程上设置中断标志位,但不会停止该线程。 - Gray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接