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

时间:2010-04-19 06:38:28

标签: java multithreading future executorservice interrupted-exception

我的代码段:

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

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

4 个答案:

答案 0 :(得分:35)

ExecutionExceptionInterruptedException是两回事。

ExecutionException包装正在执行的线程抛出的任何异常,因此,如果您的线程正在执行某种导致IOException被抛出的IO,那将被包装在{ {1}}并重新投入。

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

答案 1 :(得分:6)

如果在计算完成之前在等待线程上调用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";
        }
    }
}

答案 2 :(得分:3)

IBM Developer Works文章Dealing with InterruptedException对如何处理InterruptedException提出了一些建议。

答案 3 :(得分:0)

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

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

输出:

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:阻塞操作超时时抛出异常。

在上面的示例中,某些任务花费更多时间(由于4秒睡眠)以及get()Future的阻止操作

增加超时或优化Runnable任务。

ExecutionException:尝试检索通过抛出异常而中止的任务的结果时抛出异常=&gt;计算引发了异常

在上面的示例中,此Exception是通过ArithmeticException: / by zero

模拟的

一般来说,你应该抓住它来解决根本原因,如果它在例子中引用是微不足道的。

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

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

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