2017-04-21 53 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();