用于异步处理的短期ExecutorService

时间:2016-08-09 17:45:19

标签: java apache-zookeeper java.util.concurrent

我有一个方法可以在火中执行异步请求而忘记时尚。

方法实现如下:

private void publishWorkItem(final Object payload, final ZkWorkCompleteCallback callback)
{
    if (payload == null)
        throw new NullPointerException();

    final ExecutorService executor = Executors.newSingleThreadExecutor(PUBLISH_WORK_THREAD_FACTORY);

    try
    {
        executor.execute(() -> {

            try
            {
                if (callback != null)
                {
                    final ZkWorkItem retval = publishWorkItem(payload);
                    callback.onCompleted(retval);
                }
            }
            catch (final InterruptedException e)
            {
                // suppressed
            }
            catch (final Exception e)
            {
                LOGGER.error("Unhandled exception", e);

                if (callback != null)
                    callback.onError(e);
            }
        });
    }
    finally
    {
        executor.shutdown();
    }
}

问题是我为每个异步请求创建新的ExecutorService Executors.newSingleThreadExecutor而不是使用固定的线程池。原因是publishWorkItem(payload)方法使用CountDownLatch#await(),而Watcher反过来将阻止正在执行的线程,因为它等待publishWorkItem(payload)完成。这可能会迅速耗尽固定大小的游泳池。

final CountDownLatch latch = new CountDownLatch(1); zkClient.exists(pathToWatch, new Watcher() { @Override public void process(final WatchedEvent event) { try { extractAndDelete(baos, event.getPath()); } catch (final Exception e) { LOGGER.error("Unable to perform cleanup", e); } finally { latch.countDown(); } } }, true); ------ THIS IS THE PROBLEM (Blocks current thread) ------ latch.await(); 的简化代码

{{1}}

所以我的问题是:是否有更好的解决此类问题的方法。

我确实对应用程序进行了分析,但我没有看到任何性能问题,我担心的是它创建了大量的线程。

1 个答案:

答案 0 :(得分:0)

为什么不使用ExecutorService.newCachedThreadPool()

根据javadoc,它适合您的用例

  

这些池通常会提高执行许多短期异步任务的程序的性能......如果可用,将重用以前构造的线程

不是在publishWorkItem()的每次调用中创建新的单线程池,而是创建一个缓存的线程池一次并用于所有查询。线程数的上限为Integer.MAX_VALUE,因此您不会受限于固定线程池,但它应该创建更少的线程。