В каких случаях Future.get () генерирует исключение ExecutionException или InterruptedException - PullRequest
22 голосов
/ 19 апреля 2010

Фрагмент моего кода:

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 ]

36 голосов
/ 22 апреля 2010

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

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

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

6 голосов
/ 19 апреля 2010

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";
        }
    }
}
3 голосов
/ 19 апреля 2010

Статья IBM Developer Works Работа с InterruptedException содержит несколько советов о том, как обрабатывать InterruptedException.

0 голосов
/ 01 июля 2016

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

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 : Возникло исключение при попытке получить результат задачи, которая была прервана с помощью исключения => В результате вычисления возникло исключение

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

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

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

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

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

...