English 中文(简体)
In what cases does Future.get() throw ExecutionException or InterruptedException
原标题:

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 InterruptedException and ExecutionException in the code?

And in what cases, are these exceptions thrown?

最佳回答

ExecutionException and InterruptedException are two very different things.

ExecutionException wraps whatever exception the thread being executed threw, so if your thread was, for instance, doing some kind of IO that caused an IOException to get thrown, that would get wrapped in an ExecutionException and rethrown.

An InterruptedException is 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.

问题回答

InterruptedException will be thrown if interrupt is called on the waiting thread before the computation has completed.

ExecutionException will be thrown if the computation involved (Task in this case) throws an exception itself.

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

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.

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

Either increase the time-out or optimize Runnable task.

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

In above example, this Exception is simulated through 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.

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

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





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签