2017-04-21 8 views
0

私はいくつかのキューにメッセージを送信するメソッドproducer.postMessage(メッセージ)を持っています。何らかの理由で一定期間内にメッセージを送信できなかった場合は、このタスクをキャンセルする必要があります。私は以下の実装を思いついた。私の質問は、割り込みがある場合は、未来のタスク/エグゼキュータサービスがすべてシャットダウンされていることを確認することができますし、終了していないスレッドなしでこれを動作させるために必要な変更はありません。たくさんスレッドが確実にクリーンアップされる方法

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

はなぜ代わりに 'shutdown'方法の' shutdownNow'を使用していませんか?また、 'isTerminated'メソッドは、すべてのタスクの正常終了をチェックするために使用できます。 –

答えて

0

おかげで執行上のshutdown()方法は、新しいタスクを受け入れてからそれを停止するが、実行中のタスクを完了しようとします。現在実行中のタスクが停止されていることを実行者に要求するには、方法shutdownNow()を使用する必要があります。

ただし、将来のオブジェクトでメソッドcancel(boolean mayInterruptIfRunning)を使用する場合は、これは必須ではありません。 f.get(5, TimeUnit.SECONDS)は、タスクが完了するまでに最大5秒間待ってから復帰します。 CallableではなくRunnableを送信するため、返品は常にnullになります。 Runnableは結果を返すことはできませんが、Callableは結果を返すことができます。あなたができることは、5秒のタイムアウトでgetの後にFutureにisDone()を呼び出し、falseを返した場合にはタスクが完了していないことを意味します。その場合、タスクのキャンセルを試みるために、未来にcancel(true)を呼び出すことができます。真の引数は、未来がスレッドが実行中の場合、スレッドを中断させることを示します。 RunnableでInterruptedExceptionsをキャッチしてログに記録することができます。ただし、すべての呼び出しが割り込み要求に応答するわけではないことに注意してください(たとえば、一部の入出力操作はJava NIOの多くの機能とは異なります)。

エグゼキュータのシャットダウンを呼び出す必要はなくなりました。これは、単一のタスクでのみ使用され、他の待機中または実行中のタスクがないからです。

だからあなたのコードはなる:

f.get(5, TimeUnit.SECONDS); 
if (!f.isDone()) 
    f.cancel(true); 
ex.shutdown(); 
関連する問題