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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2665569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:32:34  来源:igfitidea点击:

In what cases does Future.get() throw ExecutionException or InterruptedException

javamultithreadingfutureexecutorserviceinterrupted-exception

提问by java_geek

My code snippet:

我的代码片段:

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();
}

How should i handle the InterruptedExceptionand ExecutionExceptionin the code?

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

And in what cases, are these exceptions thrown?

在什么情况下,会抛出这些异常?

采纳答案by Nathan Hughes

ExecutionExceptionand InterruptedExceptionare two very different things.

ExecutionException并且InterruptedException是两个非常不同的东西。

ExecutionExceptionwraps whatever exception the thread being executed threw, so if your thread was, for instance, doing some kind of IO that caused an IOExceptionto get thrown, that would get wrapped in an ExecutionExceptionand rethrown.

ExecutionException包装正在执行的线程抛出的任何异常,因此,例如,如果您的线程正在执行某种导致 anIOException被抛出的 IO ,那么它将被包裹在 an 中ExecutionException并重新抛出。

An InterruptedExceptionis not a sign of anything having gone wrong. It is there to give you a way to let your threads know when it's time to stop so that they can finish up their current work and exit gracefully. Say I want my application to stop running, but I don't want my threads to drop what they're doing in the middle of something (which is what would happen if I made them daemon threads). So when the application is being shutdown, my code calls the interrupt method on these threads, which sets the interrupt flag on them, and the next time those threads are waiting or sleeping they check the interrupt flag and throw an InterruptedException, which I can use to bail out of whatever infinite-loop processing/sleeping logic the threads are engaged in. (And if the thread doesn't wait or sleep, it can just check the interrupt flag periodically.) So it is an instance of an exception being used to change the logical flow. The only reason you would log it at all is in an example program to show you what's happening, or if you're debugging a problem where interrupt logic is not working correctly.

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

回答by Jon Skeet

InterruptedExceptionwill be thrown if interruptis called on the waiting thread before the computation has completed.

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

ExecutionExceptionwill be thrown if the computation involved (Taskin this case) throws an exception itself.

ExecutionException如果所涉及的计算(Task在这种情况下)本身抛出异常,则将抛出异常。

How you want to handle this will entirely depend on your application.

您想如何处理这将完全取决于您的应用程序。

EDIT: Here's a demonstration of being interrupted:

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

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";
        }
    }
}

回答by finnw

The IBM Developer Works article Dealing with InterruptedExceptionhas some advice on how to handle InterruptedException.

IBM Developer Works 文章处理 InterruptedException对如何处理InterruptedException.

回答by Ravindra babu

Sample code to return three types of Exceptions.

返回三种异常类型的示例代码。

import java.util.concurrent.*;
import java.util.*;

public class ExceptionDemo{
    public static void main(String args[]){
        int poolSize=1;
        int maxPoolSize=1;
        int queueSize=30;
        long aliveTive=60;
        ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
        ThreadPoolExecutor executor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
                        TimeUnit.MILLISECONDS,queue);
        List<Future> futures = new ArrayList<Future>();
        for ( int i=0; i < 5; i++){
            futures.add(executor.submit(new RunnableEx()));
        }
        for ( Iterator it = futures.iterator(); it.hasNext();){
            try {
                Future f = (Future)it.next();
                f.get(4000,TimeUnit.MILLISECONDS);
            }catch(TimeoutException terr){
                System.out.println("Timeout exception");
                terr.printStackTrace();
            }
            catch(InterruptedException ierr){
                System.out.println("Interrupted exception:");
                ierr.printStackTrace();
            }catch(ExecutionException err){
                System.out.println("Exeuction exception:");
                err.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
        executor.shutdown();
    }
}

class RunnableEx implements Runnable{
    public void run() {
        // code in here
        System.out.println("Thread name:"+Thread.currentThread().getName());
        try{
            Random r = new Random();
            if (r.nextInt(2) == 1){
                Thread.sleep(2000);
            }else{
                Thread.sleep(4000);
            }
            System.out.println("eee:"+1/0);
        }catch(InterruptedException irr){
            irr.printStackTrace();
        }
    }
}

output:

输出:

Thread name:pool-1-thread-1
Timeout exception
Thread name:pool-1-thread-1
java.util.concurrent.TimeoutException
        at java.util.concurrent.FutureTask.get(FutureTask.java:201)
        at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Exeuction exception:
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
        at java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.util.concurrent.FutureTask.get(FutureTask.java:202)
        at ExceptionDemo.main(ExceptionDemo.java:20)
Caused by: java.lang.ArithmeticException: / by zero
        at RunnableEx.run(ExceptionDemo.java:49)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)
Interrupted exception:
java.lang.InterruptedException
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
        at java.util.concurrent.FutureTask.get(FutureTask.java:199)
        at ExceptionDemo.main(ExceptionDemo.java:20)
Timeout exception
java.util.concurrent.TimeoutException
        at java.util.concurrent.FutureTask.get(FutureTask.java:201)
Thread name:pool-1-thread-1
        at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Timeout exception
java.util.concurrent.TimeoutException
        at java.util.concurrent.FutureTask.get(FutureTask.java:201)
        at ExceptionDemo.main(ExceptionDemo.java:20)

TimeoutException: Exception thrown when a blocking operation times out.

TimeoutException:阻塞操作超时时抛出的异常。

In above example, some tasks are taking more time (due to 4 seconds sleep) and blocking operation of get()on Future

在上面的例子中,一些任务需要更多的时间(由于 4 秒睡眠)并且阻塞了get()onFuture

Either increase the time-out or optimize Runnable task.

增加超时或优化 Runnable 任务。

ExecutionException: Exception thrown when attempting to retrieve the result of a task that aborted by throwing an exception => The computation threw an exception

ExecutionException: 尝试检索因抛出异常而中止的任务的结果时抛出的异常 => 计算抛出异常

In above example, this Exceptionis simulated through ArithmeticException: / by zero

在上面的例子中,这Exception是通过模拟ArithmeticException: / by zero

Generally, you should catch it fix the root cause if it is trivial as quoted in the example.

通常,如果如示例中引用的那样微不足道,您应该抓住它来修复根本原因。

InterruptedException: Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity.

InterruptedException:当线程正在等待、睡眠或以其他方式被占用,并且线程在活动之前或期间被中断时抛出。

In above example, this Exceptionis simulated by interrupting current Thread during ExecutionException.

在上面的例子中,这Exception是通过在 期间中断当前线程来模拟的ExecutionException

Generally, you should catch it don't act on it.

一般来说,你应该抓住它而不是对它采取行动。