Comment faire pour que FutureTask revienne après TimeoutException?

Dans le code ci-dessous, je signale une exception TimeoutException après 100 secondes, comme prévu. À ce stade, je m’attendrais à ce que le code sorte de main et que le programme se termine, mais l’impression continue sur la console. Comment puis-je arrêter la tâche d’exécution après expiration du délai?

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); private static  T timedCall(Callable c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { FutureTask task = new FutureTask(c); THREAD_POOL.execute(task); return task.get(timeout, timeUnit); } public static void main(Ssortingng[] args) { try { int returnCode = timedCall(new Callable() { 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; } } 

    Vous devez annuler votre tâche à l’expiration du délai (et interrompre son thread). C’est à quoi sert la méthode d’ cancel(true) . :

     private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); private static  T timedCall(FutureTask task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { THREAD_POOL.execute(task); return task.get(timeout, timeUnit); } public static void main(Ssortingng[] args) { try { FutureTask task = new FutureTask(new Callable() { 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; } 

    Votre Callable doit être capable de s’arrêter rapidement, au 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à capable de le faire grâce à l'appel de Thread.sleep() . Le fait est que futureTask.cancel(true) interrompra un autre thread, et votre code doit réagir à cette interruption. Thread.sleep() fait 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 quitter dès que possible (par exemple en lançant une new InterruptedException() ) lorsque vous trouvez que cela est vrai.

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

    Mon conseil est d’en apprendre davantage sur le mécanisme d’interruption (c’est un excellent article: Traitement de InterruptedException ) et de l’utiliser.

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

    ou arrêtez votre ExecutorService en appelant shutdownNow () …

    ou quittez la VM en appelant System.exit (0)

    en fonction de vos besoins