在什么情况下,Future.get() 会抛出 ExecutionException 或 InterruptedException。

我的代码片段:

ExecutorService executor = Executors.newSingleThreadExecutor();
try {
    Task t = new Task(response,inputToPass,pTypes,unit.getInstance(),methodName,unit.getUnitKey());
    Future<SCCallOutResponse> fut = executor.submit(t);
    response = fut.get(unit.getTimeOut(),TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
    // if the task is still running, a TimeOutException will occur while fut.get()
    cat.error("Unit " + unit.getUnitKey() + " Timed Out");
    response.setVote(SCCallOutConsts.TIMEOUT);
} catch (InterruptedException e) {
    cat.error(e);
} catch (ExecutionException e) {
    cat.error(e);
} finally {
    executor.shutdown();
}

我应该如何处理代码中的 和?InterruptedExceptionExecutionException

在什么情况下,这些异常会引发吗?


答案 1

ExecutionException是两件截然不同的事情。InterruptedException

ExecutionException包装正在执行的线程引发的任何异常,因此,例如,如果您的线程正在执行某种导致抛出的 IO,则该线程将被包装在 a 中并重新抛出。IOExceptionExecutionException

An 不是任何出错的迹象。它为您提供了一种方法,让您的线程知道何时该停止,以便他们可以完成当前工作并优雅地退出。假设我希望我的应用程序停止运行,但我不希望我的线程在中间删除它们正在执行的操作(如果我将它们设置为守护程序线程,就会发生这种情况)。因此,当应用程序关闭时,我的代码在这些线程上调用中断方法,该方法在它们上设置中断标志,下次这些线程等待或休眠时,它们会检查中断标志并抛出一个 ,我可以用来拯救线程参与的任何无限循环处理/休眠逻辑。 它可以定期检查中断标志。因此,它是用于更改逻辑流的异常实例。您记录它的唯一原因是在示例程序中向您展示正在发生的事情,或者如果您正在调试中断逻辑无法正常工作的问题。InterruptedExceptionInterruptedException


答案 2

InterruptedException如果在计算完成之前在等待线程上调用,则将抛出。interrupt

ExecutionException如果所涉及的计算(在本例中)本身引发异常,则将引发。Task

您希望如何处理此问题将完全取决于您的应用程序。

编辑:这是被打断的演示:

import java.util.concurrent.*;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        Future<String> future = executor.submit(new SlowCallable());
        executor.submit(new Interruptor(Thread.currentThread()));
        try
        {
            System.out.println(future.get());
        }
        catch (InterruptedException e)
        {
            System.out.println("I was interrupted");
        }
    }

    private static class Interruptor implements Callable<String>
    {
        private final Thread threadToInterrupt;

        Interruptor(Thread threadToInterrupt)
        {
            this.threadToInterrupt = threadToInterrupt;
        }

        public String call() throws Exception
        {
            Thread.sleep(2000);
            threadToInterrupt.interrupt();
            return "interrupted other thread";
        }
    }

    private static class SlowCallable implements Callable<String>
    {
        public String call() throws Exception
        {
            Thread.sleep(5000);
            return "finished";
        }
    }
}