9
votes

Comment puis-je obtenir futuretask pour revenir après le délai d'exception?

Dans le code ci-dessous, j'attrape une expression temporelle après 100 secondes comme prévu. À ce stade, je m'attendrais à ce que le code quitte le Main et le programme de résilier, mais il conserve l'impression à la console. Comment puis-je obtenir la tâche pour arrêter d'exécuter après le délai d'attente? XXX


0 commentaires

3 Réponses :


2
votes

Une fois que vous avez attrapé la timeoutException, vous devez appeler la méthode Annuler (TRUE) de votre tâche ...

ou fermez votre exécutorservice en appelant shutdownow () ...

ou quittez la machine virtuelle en appelant system.exit (0)

en fonction de vos besoins


0 commentaires

11
votes

Vous devez annuler votre tâche sur le délai d'attente (et interrompre son fil). C'est ce que annuler (true) code> est pour. :

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();

private static <T> T timedCall(FutureTask<T> task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
    THREAD_POOL.execute(task);
    return task.get(timeout, timeUnit);
}


public static void main(String[] args) {
        try {
            FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
                public Integer call() throws Exception {
                        for (int i=0; i < 1000000; i++) {
                                if (Thread.interrupted()) return 1;
                                System.out.println(new java.util.Date());
                                Thread.sleep(1000);
                        }
                        return 0;
                }
            });
            int returnCode = timedCall(task, 100, TimeUnit.SECONDS);
        } catch (Exception e) {
                e.printStackTrace();
                task.cancel(true);
        }
        return;
}


5 commentaires

! Task.Cancéd () devrait être! Iscancéd () comme Djna a écrit à l'origine


Je pense que c'est beaucoup mieux d'utiliser des interruptions. Premièrement, votre code appelable n'a pas besoin de savoir sur tâche du tout. Deuxièmement, lorsque vous utilisez diverses opérations de blocage dans votre code appelable (comme thread.sleep () ), ceux-ci ne réagiront pas à la tâche.iscellé (), mais réagit généralement aux interruptions. Ainsi, en utilisant annuler (true) et que votre code conscient des interruptions est généralement le meilleur moyen de le faire. (Votre code sera également plus général, car le mécanisme d'interruption est si largement utilisé en Java)


Je suppose que mon point est que "l'interruption est un mécanisme coopératif". ( ibm.com/developerworks/java/library/j-jtp05236.html )


@Peter bel article! J'ai changé la réponse en conséquence.


Le code Cleary n'est pas testé. Tâche serait indéfini dans Catch bloc



4
votes

Votre appelable doit être capable de s'arrêter rapidement, en cas de besoin.

Votre code: xxx

est déjà capable de le faire grâce à l'appelant .sleep () . Point est que futuetask.cancel (true) interrompt l'autre thread et que votre code doit réagir à cette interruption. thread.sleep () Est-ce que cela. Si vous n'avez pas utilisé thread.sleep () ou un autre code de blocage interruptible, vous devez vérifier thread.CurrentThread (). Isinterrupted () par vous-même, et quitte Dès que possible (par exemple, en lancant nouvelle interruptedexception () ) lorsque vous trouvez que cela soit vrai.

Vous devez appeler futuetask.cancel (vrai); < / Code> à partir de votre gestionnaire d'exception pour annuler et interrompre le fil qui exécute votre tâche.

Mon conseil est d'en savoir plus sur le mécanisme d'interruption (c'est un excellent article: traiter avec une exception interrompue ) et l'utiliser.


0 commentaires