2017-04-21 100 views
0

我有一個方法producer.postMessage(消息),這將消息發送到一些隊列。如果由於某種原因,郵件無法在一段時間內發送,我希望此任務被取消。我想到了下面的實現。我的問題是,如果有中斷,我可以確定Future task/executor服務全部關閉,如果不需要做出什麼改變,使得這個工作沒有任何線程沒有被終止。如何確保線程清理

非常感謝

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

爲什麼不使用'shutdownNow'代替'shutdown'方法? 'isTerminated'方法也可用於檢查所有任務的成功終止。 –

回答

0

上的執行者shutdown()方法將接受新的任務,阻止它,但嘗試完成正在運行的任務。您應該使用方法shutdownNow()來讓Executor請求停止當前正在運行的任務。

這可能不是必要的但是,如果你未來的對象使用方法cancel(boolean mayInterruptIfRunning)f.get(5, TimeUnit.SECONDS)將在返回前最多等待5秒完成任務。由於您提交的是Runnable而不是Callable,因此回報將始終爲空; Runnables不能返回結果,而Callables可以。你可以做的是在獲得5秒超時之後在Future上調用isDone(),如果返回false,則表示任務尚未完成。在這種情況下,您可以致電Future上的cancel(true)嘗試取消任務。真實的參數表明,如果線程正在運行,您將允許Future中斷該線程。您可能想要在您的Runnable中捕獲InterruptedExceptions並記錄它們。但是請注意,並非每個調用都可能響應中斷請求(例如,有些I/O操作可能不會,而很多Java NIO都會這樣做)。

呼籲執行關機可能不再是必要的,因爲它僅用於單個的任務,應該沒有其他等待或正在運行的任務,但它可能還是不錯的形式。

所以,你的代碼將變成:

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