【问题标题】:Shutdown executor without knowing when it will finish all the tasks在不知道何时完成所有任务的情况下关闭执行程序
【发布时间】:2021-05-12 14:27:44
【问题描述】:

我有一个任务应该等待一个条件(OpenCms 启动)然后通知一些听众。 为此,我使用了 ExecutorService:

public void check(final ExecutorService executorService) {
    executorService.submit(() -> {
        waitForInitialization();
        notifyListeners();
    });
}


private void waitForInitialization() {
        while (OpenCms.getRunLevel() < OpenCms.RUNLEVEL_4_SERVLET_ACCESS) {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

问题是如何关闭这个执行器。我可以使用awaitTermination,但我应该提供一个我不确切知道的超时。它可能因一种环境而异。

【问题讨论】:

    标签: java multithreading executorservice opencms


    【解决方案1】:

    问题是如何关闭这个执行器。我可以使用 awaitTermination 但我应该提供一个我不确切知道的超时。它可能因一种环境而异。

    我要问的问题是您是否需要超时?通常,如果您知道某项工作将在某个时候完成,我只需等待超时Long.MAX_VALUE - 永远有效。其他时候我会做类似的事情:

    1. threadPool.shutdown();
    2. threadPool.awaitTermination(...) 的值很小(可能是 10 秒)
    3. threadPool.shutdownNow(); 中断线程
    4. threadPool.awaitTermination(...); of Long.MAX_VALUE 因为我知道这些工作最终会完成

    它可能因环境而异。

    如果它可以变化,那么也许您应该能够计算出每个环境的适当超时时间?

    最后,不要害怕传入创建守护线程的ThreadFactory。对于某些工作,我 shutdown() 线程池但从不等待它们完成,因为我不关心它们的状态,所以我在启用守护进程的池中创建线程,可能使用类似于以下线程工厂的东西。

    /** Thread factory which sets name and optionally daemon */
    public class PoolNameThreadFactory implements ThreadFactory {
    
        private final String poolName;
        private final Boolean daemon;
        private final AtomicInteger threadNum = new AtomicInteger(0);
    
        public PoolNameThreadFactory(String poolName) {
            this(poolName, null);
        }
    
        public PoolNameThreadFactory(String poolName, boolean daemon) {
            this(poolName, (Boolean) daemon);
        }
    
        private PoolNameThreadFactory(String poolName, Boolean daemon) {
            this.poolName = poolName;
            this.daemon = daemon;
        }
    
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setName(poolName + '-' + threadNum.incrementAndGet());
            if (daemon != null) {
                thread.setDaemon(daemon);
            }
            return thread;
        }
    }
    

    【讨论】:

      【解决方案2】:

      根据提供的信息,我明确推荐基于事件的方法。特别是知道在你自己的代码中有一个像notifyListeners() 这样的调用。事实上,这就是要走的路。

      总而言之,一旦在您的应用中某处满足前提条件,只需将此事件通知侦听器即可。在您的示例中,“OpenCms 运行级别” 更改通常是一个事件。因此,只需使用Observer 模式或pub-sub 模型来观察或监控这些变化。

      如果您修改您的方法,您将不必担心初始化前后的等待时间,除非您希望专门处理缺少事件。这将在超时后再次执行,但优点是不会阻塞执行器线程。

      【讨论】:

      • 我的情况不能这样做,(但我同意你的观点),但我不负责满足条件,这是在另一个罐子里完成的。
      • 好的,那么我看不出有什么解决方案可以解决您的“问题”,而不是在超时后调用 shutdown() 然后 awaitTermination() 和/或 shutdownNow() 。超时(有时甚至很长)是一种很好的做法,所以我不知道还能说什么。
      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 2010-10-23
      • 2021-07-31
      • 1970-01-01
      • 2017-05-25
      • 2015-12-07
      相关资源
      最近更新 更多