Question

Dans le code ci-dessous, je suis attraper un TimeoutException au bout de 100 secondes comme prévu. À ce stade, j'attendre le code pour quitter principal et le programme de mettre fin, mais il continue d'imprimer à la console. Comment puis-je obtenir la tâche d'arrêter l'exécution après le délai?

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

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


public static void main(String[] args) {

    try {
        int returnCode = timedCall(new Callable<Integer>() {
            public Integer call() throws Exception {
                for (int i=0; i < 1000000; i++) {
                    System.out.println(new java.util.Date());
                    Thread.sleep(1000);
                }
                return 0;
            }
        }, 100, TimeUnit.SECONDS);
    } catch (Exception e) {
        e.printStackTrace();
        return;
    }


}
Était-ce utile?

La solution

Vous devez annuler votre tâche délai d'attente (et d'interrompre son fil). C'est ce que la méthode de cancel(true) 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;
}

Autres conseils

Votre doit appelable pour pouvoir arrêter rapidement, en cas de besoin.

Votre code:

public Integer call() throws Exception {
    for (int i=0; i < 1000000 && !task.cancelled(); i++) {
        System.out.println(new java.util.Date());
        Thread.sleep(1000); // throws InterruptedException when thread is interrupted
    }
    return 0;
}

est déjà en mesure de le faire grâce à l'appel Thread.sleep(). Le point est que futureTask.cancel(true) interrompra autre thread, et votre code doit réagir à cette interruption. Thread.sleep() fait cela. Si vous n'avez pas utilisé Thread.sleep() ou tout autre code de blocage interruptible, vous devez vérifier Thread.currentThread().isInterrupted() par vous-même, et quitter le plus tôt possible (par exemple en lançant new InterruptedException()) lorsque vous trouvez que cela est vrai.

Vous devez appeler futureTask.cancel(true); de votre gestionnaire d'exceptions pour annuler et interrompre fil exécute votre tâche.

Mon conseil est d'en apprendre davantage sur le mécanisme d'interruption (ce qui est excellent article: Faire face à InterruptedException), et l'utiliser.

Une fois que vous avez pris le TimeoutException, vous devez appeler la méthode cancel (true) de votre tâche ...

ou fermer votre ExecutorService en appelant shutdownNow () ...

ou quitter la machine virtuelle en appelant System.exit (0)

en fonction de vos besoins

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top