1

我想知道是否可以同时从不同线程抛出多个异常的情况。
如果是这样,如何正确处理它们以恢复应用程序并继续执行?

感谢您的回答。
欢迎好的例子。

4

2 回答 2

3

我想知道是否可以同时从不同的线程抛出多个异常的情况。

是的,有可能。

如果是这样,如何正确处理它们以恢复应用程序并继续执行?

catch块发生在抛出异常的线程中,因此每个线程都可以进行自己的清理。

如果一个catch块需要处理一个从多个线程引用的对象,那么您需要小心地正确锁定,就好像该对象可以被多个未处理异常的线程访问一样。

如果您已经安装了自定义UncaughtExceptionHandler,那么您需要在处理可变状态时在该处理程序中进行同步,以便在从多个线程同时调用时不会遇到并发问题。


如果 catch 块在启动线程的方法中怎么办?

Thread th = new Thread(new Runnable() {
  public void run() {
    throw new NullPointerException();
  }
});
th.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
  public void uncaughtException(Thread thread, Throwable throwable) {
    // This gets run because the NPE ends the child thread.
    System.err.println("Uncaught " + throwable);
  } 
});
try {
  th.start();
} catch (NullPointerException ex) {
  System.err.println("Not reached");
}

当子线程抛出异常时,未到达父堆栈帧中的 catch 块。

发生这种情况是因为启动一个线程不像分叉一个进程。当 fork 一个进程时,子进程获取父进程堆栈的副本,​​但是当启动一个线程时,子进程从它自己的空堆栈开始。

于 2013-04-11T05:20:48.433 回答
1

如果多个线程依赖一个资源才能工作,而该资源有错误,那么使用该资源的线程都会抛出异常。你想如何处理这取决于你,但我建议每个线程处理它自己的异常,除非你有另一个线程来管理这些线程并为它们处理异常。

例如,在我去年夏天制作的一款游戏中,我的声音系统有很多通道,每个通道都有自己的线程,还有一个线程负责加载声音数据并将其添加到通道中。我最初为每个线程使用 Clip 对象,如果太多剪辑试图播放相同的声音,有时会导致错误。我为每个频道添加了一个标志,以判断是否在频道中引发了异常。如果我的声音管理器在尝试添加声音时发现一个错误的通道,它将删除该通道,在其位置添加一个新通道,并将字符串提供给通道以引用内存中加载的声音字节。同时使用 Clip 接口的许多线程还存在其他问题。在极少数情况下,整个虚拟机会由于“不支持小型转储”而失败。由于 catch 子句无法阻止虚拟机错误,我切换到另一种音效播放方法:SourceDataLine。我没有问题。

运行多个线程还有更多可能的错误。有很多方法可以处理这些错误。

于 2013-04-11T05:35:59.837 回答