【问题标题】:Properly shut down ThreadPoolExecutors正确关闭 ThreadPoolExecutors
【发布时间】:2015-10-20 01:45:32
【问题描述】:

我是 Java 并发的新手,想问以下基本问题。我正在创建一个 ThreadPoolExecutor 来提高性能,如下所示:

int n = Runtime.getRuntime().availableProcessors()
ExecutorService executor = Executors.newFixedThreadPool(n);
for( int i = 0; i < n; i++)
            executor.execute(new Work());

在线程池中的所有线程完成任务后,我需要正确关闭池。我会尝试这个:

while(true){
    if(executor.isTerminated()){
        executor.shutdownNow();
        break;
    }
}

但我不确定这一点,因为我认为我们浪费了大量的处理器资源来查询执行程序是否终止。

什么是正确的解决方案?

UPD:可运行任务:

public class Work implements Runnable{

    private String sql;

    public Work() {
        //init sql
    }
    @Override
    public void run() {
        JdbcTemplate template = new JdbcTemplate(dataSource);
        @SuppressWarnings("unchecked")
        List<Integer> ints = template.queryForList(sql, Integer.class);
        //Storing the list into a global cache
    }

}

【问题讨论】:

  • 你也可以展示 Runnable 类吗?您的线程实现使您的线程可以安全关闭,您应该根据安全关闭来编写它们
  • 请参阅this answer 类似问题。
  • @Neron 当然,更新
  • 来自the documentation:“请注意,isTerminated 永远不会是true,除非首先调用shutdownshutdownNow”。所以你的代码根本没有意义。

标签: java multithreading


【解决方案1】:
  try {
            executor = Executors.newSingleThreadExecutor();
            future = executor.submit(task);
            executor.shutdown();
            executor.awaitTermination(5, TimeUnit.SECONDS);
        }
        finally {
            if (Objects.nonNull(executor) && !executor.isTerminated()) {
                LOGGER.error("cancelling all non-finished tasks");
            }
            if (Objects.nonNull(executor)) {
                executor.shutdownNow();
                LOGGER.info("shutdown finished");
            }
        }

这样你关闭执行器并等待5秒完成所有任务,然后最后调用executor.shutdownNow()完全杀死执行器。

这是关闭执行器的最佳方式。

【讨论】:

    【解决方案2】:

    关闭ExecutorService 似乎有些神秘。

    来自the documentation of shutdown()

    启动有序关闭,执行之前提交的任务,但不会接受新任务。

    所以您所要做的就是在您提交所有任务后调用shutdown(),确切的时间并不重要。他们不必在那个时候完成。 ThreadPoolExecutor 将完成所有任务,然后清理所有资源。

    无论您是否等待,它都会这样做。所以你不需要等待,当你确信你不会提交新任务时调用shutdown(),其余的会尽快发生。

    【讨论】:

      【解决方案3】:

      上面写着:

      除了尽力停止处理之外,没有任何保证 积极执行任务。例如,典型的实现将 通过 Thread.interrupt() 取消,因此任何无法响应的任务 中断可能永远不会终止。

      http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()

      所以请改用 awaitTermination。对于需要时间的线程,使用布尔变量作为 volatile 并检查它是否设置在外部。如果设置则退出等类似的东西

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-26
        • 1970-01-01
        • 2019-10-07
        • 2012-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多