【问题标题】:Is it possible for two ExecutorServices to share a thread pool?两个 ExecutorService 是否可以共享一个线程池?
【发布时间】:2023-03-07 19:21:01
【问题描述】:

我有一组要处理的记录,并且可以并行处理,所以我创建了一个ExecutorService(通过Executors#newCachedThreadPool())。单个记录的处理本身是由可并行化的步骤组成的,所以我想使用另一个ExecutorService。有没有一种简单的方法可以让这个新线程使用相同的底层线程池?它甚至是可取的吗?谢谢。

【问题讨论】:

    标签: java concurrency threadpool


    【解决方案1】:

    回答您的问题:,两个ExecutorService 对象不能共享一个线程池。但是,您可以在对象之间共享 ExecutorService,或者根据需要创建多个 Executor,尽管不太推荐这样做。

    最佳解决方案:在您的对象之间共享Executor

    【讨论】:

      【解决方案2】:

      简短回答:不。

      更长的答案:您需要自己的实现来做到这一点。 ExecutorService 是一个接口,AbstractExecutorService 很容易实现。 如果你想让两个ExecutorService共享同一个线程池(例如具有不同的最大活跃线程值),你可以使用代理模式使线程池共享ExecutorService

      【讨论】:

      • 谢谢!代理模式在这里会很漂亮。为可插入线程池复制 Doug Lea 的代码太容易出错了。
      • (我的用例是我需要等到每个 Executor 完成所有任务。也就是说,使用 shutdown()/awaitTermination() 方法)
      【解决方案3】:

      您可以将现有 ExecutorService 的引用传递给您的工作对象吗?

      public class Task implements Runnable {
          private final ExecutorService threadPool;
          private final SubTask[] subtasks;
      
          public Task(ExecutorService threadPool) {
              this.threadPool = threadPool;
              this.subtasks = createSubtasksIGuess();
          }
      
          public void run() {
              for(SubTask sub : subtasks)
                  threadPool.submit(sub);
          }
      }
      

      【讨论】:

        【解决方案4】:

        有几个很好的理由想要这样做,例如每个队列的单独边界和指标。 AFAIK,Cassandra 2.1 通过使用具有共享线程池的执行器服务实现获得了不小的好处;代码位于https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/concurrent/SEPExecutor.java

        【讨论】:

        • 当然,最初的问题要求直接使用 Java 7 中提供的 fork/join 任务 API。
        • 我最近的另一个用例是有一个带有单个队列但有两个执行器的单线程池,其中一个使用AbortPolicy,另一个使用CallerRunsPolicy
        猜你喜欢
        • 1970-01-01
        • 2019-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        • 2016-03-10
        • 2017-03-12
        相关资源
        最近更新 更多