web-dev-qa-db-fra.com

Dans quels cas Future.get () lève-t-il ExecutionException ou InterruptedException

Mon extrait de code:

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

Comment dois-je gérer les InterruptedException et ExecutionException dans le code? 

Et dans quels cas, ces exceptions sont-elles levées?

21
java_geek

ExecutionException et InterruptedException sont deux choses très différentes.

ExecutionException enveloppe quelle que soit l'exception que le fil en cours d'exécution a jeté, donc si votre fil était, par exemple, en train de faire une sorte de IO qui a provoqué le lancement d'une IOException, celui-ci serait enveloppé dans un ExecutionException et renversé.

Un InterruptedException n'est pas le signe que quelque chose a mal tourné. Il est là pour vous permettre de faire savoir à vos discussions à quel moment il est temps de s’arrêter afin qu’elles puissent terminer leur travail en cours et se quitter en douceur. Dites que je veux que mon application cesse de fonctionner, mais je ne veux pas que mes threads abandonnent ce qu'ils font au milieu de quelque chose (ce qui se produirait si je leur créais des threads démon). Donc, lorsque l'application est en train d'être arrêtée, mon code appelle la méthode d'interruption sur ces threads, ce qui définit l'indicateur d'interruption sur eux et la prochaine fois que ces threads attendent ou se mettent en sommeil, ils vérifient l'indicateur d'interruption et lancent une InterruptedException, que je peux utiliser. pour sortir de toute logique de traitement/boucle en boucle infinie dans laquelle les threads sont engagés. (Et si le thread n'attend pas ou ne dort pas, il peut simplement vérifier l'indicateur d'interruption périodiquement.) Il s'agit donc d'une instance d'une exception utilisée. pour changer le flux logique. La seule raison pour laquelle vous le consignerez est dans un exemple de programme pour vous montrer ce qui se passe ou si vous corrigez un problème où la logique d'interruption ne fonctionne pas correctement.

InterruptedException sera levé si interrupt est appelé sur le thread en attente avant la fin du calcul.

ExecutionException sera levé si le calcul impliqué (Task dans ce cas) lève une exception elle-même.

La façon dont vous souhaitez gérer cela dépendra entièrement de votre application.

EDIT: Voici une démonstration de l'interruption:

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";
        }
    }
}
6
Jon Skeet

L'article d'IBM Developer Works Gestion de l'InterruptedException contient des conseils sur la façon de gérer InterruptedException.

3
finnw

Exemple de code pour renvoyer trois types d'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();
        }
    }
}

sortie:

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 levée lorsqu'une opération de blocage expire. 

Dans l'exemple ci-dessus, certaines tâches prennent plus de temps (en raison d'une veille de 4 secondes) et bloquent le fonctionnement de get() sur Future 

Augmentez le délai d'expiration ou optimisez la tâche Runnable.

ExecutionException : Exception levée lors d'une tentative d'extraction du résultat d'une tâche qui a été annulée en lançant une exception => Le calcul a renvoyé une exception

Dans l'exemple ci-dessus, cette Exception est simulée par ArithmeticException: / by zero

En règle générale, vous devriez corriger la cause du problème si elle est triviale, comme indiqué dans l'exemple.

InterruptedException : Émis lorsqu'un thread est en attente, en veille ou occupé d'une autre manière et que le thread est interrompu, que ce soit avant ou pendant l'activité. 

Dans l'exemple ci-dessus, cette Exception est simulée en interrompant le thread actuel pendant ExecutionException.

Généralement, vous devriez attraper cela et ne pas agir dessus.

0
Ravindra babu