如何确保清理线程

时间:2017-04-21 09:53:11

标签: java multithreading future

我有一个方法producer.postMessage(message),它将消息发送到某个队列。如果由于某种原因在一段时间内无法发送消息,我希望取消此任务。我想出了下面的实现。我的问题是,如果存在中断,我可以确定Future任务/执行程序服务都已关闭,如果没有,需要进行哪些更改才能使此工作在没有任何线程未被终止的情况下。

非常感谢

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");
    }
}

1 个答案:

答案 0 :(得分:0)

Executor上的shutdown()方法将阻止它接受新任务,但会尝试完成正在运行的任务。您应该使用方法shutdownNow()来获取当前正在运行的任务的Executor请求。

但是,如果在Future对象上使用方法cancel(boolean mayInterruptIfRunning),则可能不需要这样做。在返回之前,f.get(5, TimeUnit.SECONDS)将等待最多5秒以完成任务。由于您提交的是Runnable而不是Callable,因此返回值始终为null; Runnables无法返回结果,而Callables可以。您可以做的是在获得5秒超时之后在Future上调用isDone(),如果返回false,则表示任务尚未完成。在这种情况下,您可以在Future上调用cancel(true)来尝试取消该任务。 true参数表明如果线程正在运行,你将允许Future中断该线程。您可能希望在Runnable中捕获InterruptedExceptions并记录它们。但是请注意,并非每个调用都可以响应中断请求(例如,某些I / O操作可能没有,而很多Java NIO都会这样做。)

可能不再需要在执行程序上调用关闭,因为它仅用于单个任务,并且不应该有其他等待或正在运行的任务,但它可能仍然是良好的形式。

所以你的代码会变成:

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