如何在FutureTask中捕获异常
如何在FutureTask中捕获异常
在发现在Java 1.6(以及来自Eclipse)中运行在Executors.newCachedThreadPool()
上的FutureTask
会吞噬在Runnable.run()
方法中的异常后,我尝试想出一种方法来捕获这些异常,而不需要在所有的Runnable
实现中添加throw/catch语句。\nAPI建议重写FutureTask.setException()
方法应该有助于解决这个问题:\n
\n除非该Future已经被设置或已被取消,否则导致该Future报告带有给定throwable作为其原因的ExecutionException。在计算失败时,此方法由run方法在内部调用。\n
\n然而,这个方法似乎没有被调用(在调试器中运行显示异常被FutureTask
捕获,但没有调用setException
)。我编写了以下程序来重现我的问题:\n
public class RunTest { public static void main(String[] args) { MyFutureTask t = new MyFutureTask(new Runnable() { @Override public void run() { throw new RuntimeException("Unchecked exception"); } }); ExecutorService service = Executors.newCachedThreadPool(); service.submit(t); } } public class MyFutureTask extends FutureTask
\n我的主要问题是:我如何捕获在FutureTask中抛出的异常?为什么不调用setException
方法?\n此外,我想知道为什么Thread.UncaughtExceptionHandler
机制没有被FutureTask
使用,这是否有任何原因?
问题的出现原因是在调用futureTask.get()
方法来获取计算结果时,如果底层的Runnable
/Callable
抛出了异常,它会抛出一个ExecutionException
异常。ExecutionException.getCause()
方法将返回Runnable
/Callable
抛出的异常。如果Runnable
/Callable
被取消了,它还会抛出另一个异常。
解决方法是使用try-catch块来捕获ExecutionException
异常,并使用getCause()
方法获取底层异常。如果希望处理Runnable
/Callable
被取消的情况,可以使用isCancelled()
方法来检查任务是否被取消。
以下是一个示例代码来演示如何捕获ExecutionException
异常:
try { Object result = futureTask.get(); // 处理计算结果 } catch (ExecutionException e) { Throwable cause = e.getCause(); // 处理底层异常 } catch (InterruptedException e) { // 处理任务被中断的情况 }
通过使用try-catch块来捕获异常,可以确保在FutureTask中抛出的异常能够被正确处理,从而避免程序的崩溃和错误的结果。
如何在FutureTask中捕获异常
在使用FutureTask时,如果想要捕获异常,可以尝试使用UncaughtExceptionHandler。
你需要实现UncaughtExceptionHandler接口。
要为线程池线程设置UncaughtExceptionHandler,可以在Executor.newCachedThreadPool(ThreadFactory)调用中提供ThreadFactory。
可以通过setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)为创建的线程设置UncaughtExceptionHandler。
使用ExecutorService.execute提交任务,因为只有使用execute提交的任务抛出的异常才会传递到未捕获的异常处理器。对于使用ExecutorService.submit提交的任务,抛出的任何异常都被认为是任务的返回值的一部分。如果使用submit提交的任务以异常终止,调用Future.get时会重新抛出该异常,并用ExecutionException包装。
提交任务时我错误地使用了ExecutorService.submit。
代码示例:
Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) { System.out.println("Uncaught exception: " + e); } }; ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactory() { public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setUncaughtExceptionHandler(handler); return thread; } }); FutureTasktask = new FutureTask<>(new Callable () { public String call() throws Exception { // Task code here return "Result"; } }); executor.execute(task); try { String result = task.get(); // Handle the result } catch (ExecutionException e) { // Handle the exception }
如何在FutureTask中捕获异常
在使用FutureTask时,有时候我们需要捕获可能发生的异常并对其进行处理。下面是一个可能出现的问题以及解决方法。
问题原因:
setException可能不是用于重写的,而是用于在需要时将结果设置为异常状态。因此,我们需要重写done()方法并尝试获取结果。
解决方法:
我们可以创建一个继承自FutureTask的类,并重写done()方法来捕获异常。在done()方法中,我们可以尝试获取结果并处理异常。
代码示例:
public class MyFutureTask extends FutureTask
如何从ExecutionException对象中获取状态码?
如果你想获取导致ExecutionException的异常,你可以像我在println语句中所做的那样使用getCause()方法。
我尝试了相同的方法,使用e.getCause(),我能够获取Throwable对象和错误消息,但我需要检索networkResponse对象,其中包含状态码。
你可以通过向合适的类型进行强制转换来获取networkResponse对象(最好在instanceof检查之后)。