如何在Java中捕获另一个线程抛出的异常?

8

我正在使用一个创建自己线程的库,它抛出了一个异常。我该如何捕获这个异常?异常是在下面标记的那一行抛出的:

ResourceDescriptor rd = new ResourceDescriptor();
        rd.setWsType(ResourceDescriptor.TYPE_FOLDER);
        fullUri += "/" + token;
        System.out.println(fullUri);
        // >>> EXCEPTION THROWN ON THE FOLLOWING LINE <<<
        rd.setUriString(fullUri.replaceAll("_", ""));
        try{
            rd = server.getWSClient().get(rd, null);
        }catch(Exception e){
            if(e.getMessage().contains("resource was not found")){
                this.addFolder(fullUri, label, false);
                System.out.println("Folder does not exist, will be added now.");
            }else{
                System.out.println("Error Messages: " + e.getMessage());
            }
        }

1
你如何调用抛出异常的方法?(还可能是:你如何知道是否抛出了异常?) - DerMike
我已经尝试捕获通用异常类,但仍然出现了异常抛出的情况。我在谷歌上搜索了一下,似乎是由我正在使用的库中的另一个线程引起的。这个库通过网络服务与一个Web应用程序进行交互。 - yuejdesigner85
2个回答

21

3
+1 我不知道这个。这比我回答的更好。 - Gray
我无法控制我所使用的库所创建的线程,因此我无法在它们的线程上显式设置未捕获异常处理程序。我该怎么办? - yuejdesigner85
看一下这里。这样你就可以获取Thread对象了;) 当然,这并不是一个很干净的解决方案,但值得一试。 - Ortwin Angermeier
如果我捕获了异常,那么我该怎么访问它(也许通过代理)? - NeverJr

7
如果你只有一个Thread对象,那么就没有办法捕获任何异常(我假设这些异常是RuntimeException)。正确的方法是使用ExecutorService使用的Future类,但我假设你无法控制启动Thread的代码。
如果你提供了Runnable或者将代码注入库中,那么你可以将它包装在一个类中,以捕获和保存异常,但前提是异常在你的代码中或从你调用的代码中抛出。类似以下内容:
final AtomicReference<Exception> exception = new AtomicReference<Exception>();
Thread thread = library.someMethod(new Runnable() {
   public void run() {
      try {
         // call a bunch of code that might throw
      } catch (Exception e) {
         // store our exception thrown by the inner thread
         exception.set(e);
      }
   }
});
// we assume the library starts the thread
// wait for the thread to finish somehow, maybe call library.join()
thread.join();
if (exception.get() != null) {
   throw exception.get();
}

此外,如果您正在分叉自己的线程,还可以设置未捕获异常处理程序:
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
   public void uncaughtException(Thread t, Throwable e) {
      // log it, dump it to the console, or ...
   }
});

但是,如果库内部的线程代码无法由您进行包装,则不起作用。 如果您编辑问题并显示一些代码并提供更多详细信息,我可以编辑我的问题以提供更好的帮助。


如果您提供的是 Thread 而不是 Runnable,则可以重写 join 方法。这将允许您检查线程是否因异常退出,并在加入线程的上下文中重新抛出异常。 - ccurtsinger
@artbristol 你说得对。这很不幸。 - ccurtsinger
目前我无法控制该库,因为它已经编译完成。 - yuejdesigner85
很好的解释。您能详细说明一下如何使用“Future”可以帮助吗? - flow2k
“Future” 允许你使用执行器服务,但仍可获取池中线程抛出的异常 @flow2k。 - Gray

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