2017-04-21 1 views
0

J'ai une méthode producer.postMessage (message) qui envoie un message à une file d'attente. Si, pour une raison quelconque, le message n'a pas pu être envoyé dans un délai donné, je souhaite que cette tâche soit annulée. Je suis venu avec la mise en œuvre ci-dessous. Ma question est la suivante: s'il y a une interruption, puis-je m'assurer que le service Tâche/exécuteur Futur est éteint? Sinon, quels changements doivent être faits pour que cela fonctionne sans que les tâches soient terminées?Comment être sûr que les threads sont nettoyés

Merci beaucoup

public void postMessage(final Object object) 
{ 
    LOG.debug("postMessage object " + object.getClass().getSimpleName()); 

    Message message = new Message("task", 10, object); 

    try 
    { 
     ExecutorService ex = Executors.newSingleThreadExecutor(); 
     Future<?> f = ex.submit(new Runnable() 
     { 
      public void run() 
      { 
       producer.postMessage(message); 
       LOG.debug("Finished sending message for " + object.getClass().getSimpleName()); 
      } 
     }); 
     f.get(5, TimeUnit.SECONDS); 
     ex.shutdown(); 
    } 
    catch (InterruptedException | ExecutionException | TimeoutException e) 
    { 
     LOG.error("Could not deliver message to the queue, Check AMQ is running"); 
    } 
} 
+0

pourquoi ne pas utiliser 'shutdownNow' au lieu de méthode' shutdown'? La méthode 'isTerminated' peut également être utilisée pour vérifier l'aboutissement de toutes les tâches. –

Répondre

0

La méthode shutdown() sur un Executor va arrêter d'accepter de nouvelles tâches, mais les tentatives pour accomplir les tâches en cours d'exécution. Vous devez utiliser la méthode shutdownNow() pour demander à l'Executor d'arrêter les tâches en cours d'exécution.

Cela peut ne pas être nécessaire si vous utilisez la méthode cancel(boolean mayInterruptIfRunning) sur l'objet Future. f.get(5, TimeUnit.SECONDS) attendra au plus 5 secondes pour l'achèvement des tâches avant de revenir. Puisque vous soumettez un Runnable plutôt qu'un Callable, le retour sera toujours nul; Les exécutables ne peuvent pas retourner un résultat, alors que les Callables le peuvent. Ce que vous pouvez faire, c'est appeler le isDone() sur le Futur après le get avec un délai de 5 secondes, et s'il renvoie false, cela signifie que les tâches ne sont pas terminées. Dans ce cas, vous pouvez appeler le cancel(true) sur le futur pour tenter d'annuler la tâche. L'argument true indique que vous autoriserez le Future à interrompre le thread s'il est en cours d'exécution. Vous voudrez peut-être attraper InterruptedExceptions dans votre Runnable et les enregistrer. Notez toutefois que tous les appels ne peuvent pas répondre aux demandes d'interruption (par exemple, certaines opérations d'E/S peuvent ne pas répondre, contrairement à beaucoup de tâches Java NIO). L'appel de l'arrêt sur l'exécuteur peut ne plus être nécessaire car il est utilisé uniquement pour une seule tâche et ne devrait pas avoir d'autres tâches en attente ou en cours d'exécution, mais c'est probablement encore une bonne forme.

Ainsi, votre code serait:

f.get(5, TimeUnit.SECONDS); 
if (!f.isDone()) 
    f.cancel(true); 
ex.shutdown();