我想知道是否可以同时从不同线程抛出多个异常的情况。
如果是这样,如何正确处理它们以恢复应用程序并继续执行?
感谢您的回答。
欢迎好的例子。
我想知道是否可以同时从不同线程抛出多个异常的情况。
如果是这样,如何正确处理它们以恢复应用程序并继续执行?
感谢您的回答。
欢迎好的例子。
我想知道是否可以同时从不同的线程抛出多个异常的情况。
是的,有可能。
如果是这样,如何正确处理它们以恢复应用程序并继续执行?
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 一个进程时,子进程获取父进程堆栈的副本,但是当启动一个线程时,子进程从它自己的空堆栈开始。
如果多个线程依赖一个资源才能工作,而该资源有错误,那么使用该资源的线程都会抛出异常。你想如何处理这取决于你,但我建议每个线程处理它自己的异常,除非你有另一个线程来管理这些线程并为它们处理异常。
例如,在我去年夏天制作的一款游戏中,我的声音系统有很多通道,每个通道都有自己的线程,还有一个线程负责加载声音数据并将其添加到通道中。我最初为每个线程使用 Clip 对象,如果太多剪辑试图播放相同的声音,有时会导致错误。我为每个频道添加了一个标志,以判断是否在频道中引发了异常。如果我的声音管理器在尝试添加声音时发现一个错误的通道,它将删除该通道,在其位置添加一个新通道,并将字符串提供给通道以引用内存中加载的声音字节。同时使用 Clip 接口的许多线程还存在其他问题。在极少数情况下,整个虚拟机会由于“不支持小型转储”而失败。由于 catch 子句无法阻止虚拟机错误,我切换到另一种音效播放方法:SourceDataLine。我没有问题。
运行多个线程还有更多可能的错误。有很多方法可以处理这些错误。