MST
星途 面试题库

面试题:Java Future与Callable接口的异常处理机制

在使用Java的Future与Callable接口时,如果Callable任务在执行过程中抛出异常,如何通过Future获取并处理这些异常?请详细说明异常处理的流程以及可能涉及到的方法,并给出代码示例。此外,解释一下Future的isDone()、isCancelled()方法与异常处理之间的关系。
18.6万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. 异常处理流程及方法
    • Callable任务在执行过程中抛出异常时,Futureget()方法会重新抛出该异常。我们可以在调用get()方法的地方通过try - catch块捕获并处理异常。
    • Futureget()方法有两个重载形式:
      • V get():会阻塞调用线程,直到Callable任务完成并返回结果或者抛出异常。如果任务抛出异常,get()方法会重新抛出该异常。
      • V get(long timeout, TimeUnit unit):同样会阻塞调用线程,但如果超过指定的timeout时间任务仍未完成,会抛出TimeoutException。如果任务在此之前抛出异常,get()方法同样会重新抛出该异常。
  2. 代码示例
import java.util.concurrent.*;

class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        // 模拟可能抛出异常的任务
        if (Math.random() < 0.5) {
            throw new RuntimeException("任务执行过程中出现异常");
        }
        return 42;
    }
}

public class FutureExceptionHandling {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<Integer> future = executorService.submit(new MyCallable());
        executorService.shutdown();

        try {
            Integer result = future.get();
            System.out.println("任务执行结果: " + result);
        } catch (InterruptedException | ExecutionException e) {
            if (e instanceof ExecutionException) {
                Throwable cause = e.getCause();
                System.out.println("捕获到任务中的异常: " + cause.getMessage());
            } else {
                System.out.println("线程被中断: " + e.getMessage());
            }
        }
    }
}
  1. isDone()isCancelled()方法与异常处理的关系
    • isDone()方法:
      • 如果任务完成(正常完成、因异常完成或者被取消),isDone()方法返回true。当Callable任务抛出异常时,任务状态也会变为完成,此时isDone()返回true。我们可以通过isDone()方法来判断任务是否完成,再决定是否调用get()方法获取结果或者处理异常。例如,如果isDone()返回true,再调用get()方法时,即使任务抛出异常,get()方法也不会阻塞,而是立即重新抛出异常。
    • isCancelled()方法:
      • 如果任务在正常完成前被取消,isCancelled()方法返回true。它与异常处理没有直接关系,主要用于判断任务是否是因为被取消而结束,而不是因为正常执行完成或者抛出异常。如果任务是因为异常而结束,isCancelled()返回false