如何在FutureTask中捕获异常

8 浏览
0 Comments

如何在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 {
    public MyFutureTask(Runnable r) {
        super(r, null);
    }
    @Override
    protected void setException(Throwable t) {
        super.setException(t);
        System.out.println("Exception: " + t);
    }
}

\n我的主要问题是:我如何捕获在FutureTask中抛出的异常?为什么不调用setException方法?\n此外,我想知道为什么Thread.UncaughtExceptionHandler机制没有被FutureTask使用,这是否有任何原因?

0
0 Comments

问题的出现原因是在调用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中抛出的异常能够被正确处理,从而避免程序的崩溃和错误的结果。

0
0 Comments

如何在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;
    }
});
FutureTask task = 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
}

0
0 Comments

如何在FutureTask中捕获异常

在使用FutureTask时,有时候我们需要捕获可能发生的异常并对其进行处理。下面是一个可能出现的问题以及解决方法。

问题原因:

setException可能不是用于重写的,而是用于在需要时将结果设置为异常状态。因此,我们需要重写done()方法并尝试获取结果。

解决方法:

我们可以创建一个继承自FutureTask的类,并重写done()方法来捕获异常。在done()方法中,我们可以尝试获取结果并处理异常。

代码示例:

public class MyFutureTask extends FutureTask {
    public MyFutureTask(Runnable r) {
        super(r, null);
    }
    protected void done() {
        try {
            if (!isCancelled()) get();
        } catch (ExecutionException e) {
            // 异常发生,进行处理
            System.out.println("Exception: " + e.getCause());
        } catch (InterruptedException e) {
            // 不应该发生,因为我们在计算完成后被调用
            throw new AssertionError(e);
        }
    }
}

如何从ExecutionException对象中获取状态码?

如果你想获取导致ExecutionException的异常,你可以像我在println语句中所做的那样使用getCause()方法。

我尝试了相同的方法,使用e.getCause(),我能够获取Throwable对象和错误消息,但我需要检索networkResponse对象,其中包含状态码。

你可以通过向合适的类型进行强制转换来获取networkResponse对象(最好在instanceof检查之后)。

0