В каких случаях делает будущее.get () throw 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();
}

как я должен обрабатывать InterruptedException и ExecutionException в коде?

и в каких случаях, эти исключения?

4 ответов


ExecutionException и InterruptedException-это две совершенно разные вещи.

ExecutionException обертывает любое исключение, которое бросает выполняемый поток, поэтому, если ваш поток, например, делал какой-то IO, который вызвал IOException, который будет обернут в ExecutionException и перестроен.

исключение InterruptedException не является признаком того, что что-то пошло не так. Он здесь, чтобы дать вам способ, чтобы ваши нити знали, когда пришло время остановитесь, чтобы они могли закончить свою текущую работу и выйти изящно. Скажем, я хочу, чтобы мое приложение перестало работать, но я не хочу, чтобы мои потоки отбрасывали то, что они делают в середине чего-то (что произойдет, если я сделаю их потоками демона). Поэтому, когда приложение завершает работу, мой код вызывает метод прерывания в этих потоках, который устанавливает флаг прерывания на них, и в следующий раз, когда эти потоки ждут или спят, они проверяют флаг прерывания и бросают InterruptedException, который я могу использовать для выхода из любой обработки бесконечного цикла / спящей логики, в которой участвуют потоки. (И если поток не ждет или не спит, он может просто периодически проверять флаг прерывания.) Таким образом, это экземпляр исключения, используемого для изменения логического потока. Единственная причина, по которой вы регистрируете его вообще, - это пример программы, чтобы показать вам, что происходит, или если вы отлаживаете проблему, Где логика прерывания работает неправильно.


InterruptedException будет брошен, если interrupt вызывается в потоке ожидания до завершения вычисления.

ExecutionException будет брошен, если вычисление участвует (Task в этом случае) выдает само исключение.

как вы хотите справиться с этим будет полностью зависеть от вашего приложения.

EDIT: вот демонстрация прерывания:

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

статья IBM Developer Works работа с InterruptedException есть несколько советов о том, как обращаться InterruptedException.


пример кода для возврата трех типов исключений.

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() on Future

либо увеличить тайм-аут или оптимизировать выполняемую задачу.

ExecutionException: исключение при попытке получить результат задачи, которая прервалась, вызвав исключение => вычисление вызвало исключение

в приведенном выше примере, это Exception моделируется через ArithmeticException: / by zero

как правило, вы должны поймать его исправить первопричину, если она тривиальна, как указано в Примере.

выдачей InterruptedException: брошенный когда поток ждет, спать, или в противном случае занят, и поток прерван, или перед или во время деятельность.

в приведенном выше примере, это Exception моделируется путем прерывания текущего потока во время ExecutionException.

как правило, вы должны поймать его, не действуйте на него.