【问题标题】:Executor Service shutdown执行者服务关闭
【发布时间】:2023-03-08 11:40:02
【问题描述】:

我正在使用ExecutorService。我正在为for-loop 打开 10 个threads。所以它打开 10 threads 并且 connection 什么时候在这里关闭?在executor.shutdown()?如果是,它会关闭所有 10 个 threads 并再次打开 10 个 threads 吗?有什么我可以遵循更好的编码标准来提高性能的吗?

ExecutorService executor = Executors.newFixedThreadPool(10);
for(String str : stringList){
     for(String str1 : stringList1){
         for(String str2 : stringList2){
              executor.execute(new Runnable() {
                        @Override
                        public void run() {
                        //do something
                        }
          }
     }
}
executor.shutdown();
executor.awaitTermination(24L, TimeUnit.HOURS);

实际上我的想法是遍历loop并将数据保存在文件中并为每次迭代保存。所以我想在这里遵循最佳实践,因为我不想在后期看到任何与服务器相关的问题,例如连接问题/outOfMemory exceptions。请建议。

我自己实现了这个,但我是multi-threading 的菜鸟。所以在看到我发布的其他一些博客和帖子后得到一些澄清。请帮忙!

【问题讨论】:

    标签: java multithreading executorservice


    【解决方案1】:

    Executors.newFixedThreadPool(10) 就像它听起来的那样 - 它创建了一个线程池,最多有 10 个线程。来自the documentation

    池中的线程将一直存在,直到它被显式关闭

    因此,最佳做法是尽可能共享线程池。 不要这样做:

    for (int i = 0; i < 8; i++) {
        ExecutorService executor = Executors.newFixedThreadPool(10);
    
        for (String str1 : stringList1) {
            for (String str1 : stringList1) {
                executor.execute(new Runnable(){
                    public void run(){ /* Some work... */ }
                });
            }
        }
        executor.shutdown();
        executor.awaitTermination(24L, TimeUnit.HOURS);
    }
    

    请注意,一个新的FixedThreadPool 在 for 循环中被创建和销毁 8 次,创建/销毁线程池是创建/销毁最多 10 个线程。这很糟糕,因为它破坏了使用线程池的意义。如果您要在循环中使用池,请确保在可能的情况下重复使用它:

    ExecutorService executor = Executors.newFixedThreadPool(10);
    
    for (int i = 0; i < 8; i++) {
        for (String str1 : stringList1) {
            for (String str1 : stringList1) {
                executor.execute(new Runnable(){
                    public void run(){ /* Some work... */ }
                });
            }
        }
    }
    
    executor.shutdown();
    executor.awaitTermination(24L, TimeUnit.HOURS);
    

    最后,要注意的最后一件事是您排队的工作量。如果排队工作的速度快于线程池处理它的速度,那么队列大小将缓慢增长,直到达到OutOfMemoryException。不幸的是,没有内置方法可以检查线程池中剩余的任务数,因此您必须自己解决这个问题。

    这个概念也适用于服务器 - 如果每秒传入的请求数高于服务器每秒可以处理的请求数,持续时间足够长,那么服务器将耗尽资源并崩溃.解决方案通常是自动扩展和负载平衡,知道如何配置这些东西是业内非常有用的技能。

    【讨论】:

      【解决方案2】:

      这里的连接何时关闭?在 executor.shutdown()?如果是,是否会关闭所有 10 个线程并重新打开 10 个线程?

      一旦调用ExecutorService.html#shutdown,就不会向池中提交新的新任务,一旦池中没有任务,ExecutorService 将被关闭。

      void shutdown()
      

      启动有序关闭,其中执行先前提交的任务,但不会接受新任务。如果已经关闭,则调用没有额外的效果。

      此方法不等待先前提交的任务完成执行。使用awaitTermination 来执行此操作。

      一旦shutdown被触发,它不会再次打开10个线程,除非你重新创建ExecutorService

      实际上我的想法是遍历循环并将数据保存在文件中并为每次迭代保存。所以我想在这里遵循最佳实践,因为我不想在后期看到任何与服务器相关的问题,例如连接问题/outOfMemory 异常

      不要这样做。让我们等待ExecutorService 正确关机。

      解决问题的其他方法:等待任务完成。您可以在以下位置找到更多详细信息:

      How to properly shutdown java ExecutorService

      换个说法:

      newFixedThreadPool 创建无限的ExecutorService。在以下位置寻找其他替代方案:

      How to properly use Java Executor?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-26
        • 1970-01-01
        • 1970-01-01
        • 2016-07-10
        • 1970-01-01
        • 1970-01-01
        • 2014-10-03
        相关资源
        最近更新 更多