【问题标题】:what is the function of ThreadPoolExecutor maximumPoolSize in javajava中ThreadPoolExecutor maximumPoolSize的作用是什么
【发布时间】:2018-12-25 03:20:35
【问题描述】:

我正在为一些愚蠢的简单事情而苦苦挣扎......

我的实际项目多年来一直遇到一个未知问题,因此我决定创建一个非常简单的测试,但结果让我感到害怕......

这是测试:

ExecutorService t = new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(600));
        for (int i = 0; i < 100; i++) {
            final int i1 = i;
            t.execute(new Runnable() {

                @Override
                public void run() {
                    while (true) {
                        System.out.println(i1);
                        try {
                            Thread.sleep(5000);
                        }
                        catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            });
        }

我正在创建一个线程池,其中包含 10 个核心线程加上 20 个 maximumPoolSize 然后我给它 100 个线程,每个线程将简单地打印一个固定数字...

我的卑鄙愚蠢的想法是:

该池有 10 个线程,将随机打印 0-9,然后在一些 将创建 10 个额外线程,池将从 0-19 打印 随机的

这对我来说有点明显,因为 maxSize 是 20,在最坏的情况下它应该接受 20 个任务......

但结果是永远打印 0-9

问题是:如果从未安排额外线程执行,maximumPoolSize 的意义何在?

【问题讨论】:

  • 一点也不傻,这样做是合乎逻辑的方式,sun 选择仅在队列已满时使用maximumPoolSize,更多详情请参阅here
  • 我永远猜不到,这完全违反直觉......当明显的愿望是最大化吞吐量时,他们似乎“愿意”打击 quere 容量......你能指出我太阳的一个优势吗方式?
  • 只有 Doug Lea 真正知道(如果他记得的话)。这个想法来自他 1998 年的 PooledExecutor 课程,当时 CPU 和 jvm 非常不同,当队列已满时,也许使用额外的线程作为最后的手段是有意义的。最后一条评论here 以一种明智的方式解释了它。

标签: java multithreading threadpool threadpoolexecutor


【解决方案1】:

正如@Oleg 指出的那样,池工作正常,但有一个我不知道的实现细节。

仅当任务队列已满时才会创建额外的线程

这篇文章解释得更好: http://www.bigsoft.co.uk/blog/2009/11/27/rules-of-a-threadpoolexecutor-pool-size

举个例子。起始线程池大小为 1,核心池大小为 5,最大池大小为10,队列为100。

Sun 的方式:随着请求的进入,线程将被创建最多 5 个,然后 任务将被添加到队列中,直到达到 100。当队列 将创建最多 maxPoolSize 的全新线程。一旦所有 线程正在使用且队列已满的任务将被拒绝。作为 队列减少了活动线程的数量。

用户预期的方式:随着请求的进入,线程将被创建 到 10,然后任务将被添加到队列中,直到达到 100 哪一点他们被拒绝了。线程数将重命名为 最大直到队列为空。当队列为空时,线程将 直到剩下 corePoolSize 为止。

所以 Java 会等到你的队列爆出创建新线程之前的最后一秒...

【讨论】:

    【解决方案2】:

    是的,根据@Oleg 和您尝试的实现:

    new ThreadPoolExecutor(10, 20, 60L, TimeUnit.SECONDS, new ArrayBlockingQueue(600));

    这里,10 是 corePoolSize - 表示 Jvm 将为前 10 个任务的新任务创建新线程。其他任务将被添加到队列中,直到队列满(600 个任务)。

    20 是 maxPoolSize - JVM 最多可以创建 20 个线程。意味着如果已经有 10 个任务/线程正在运行并且队列已满,有 600 个待处理任务,并且如果还有一个新请求/任务到达队列,那么 JVM 将创建最多 20 个新线程(总线程数 = 前 10 个 + 新 10 个) ;

    new ArrayBlockingQueue(600) = 是一个总队列大小 - 它可以在其中排队 600 个任务。

    一旦所有 20 个线程都在运行并且如果有新任务到达,那么新任务将被拒绝。

    [来自文档] SUN内部创建线程的规则:

    • 如果线程数小于 corePoolSize,则创建一个新线程来运行新任务。
    • 如果线程数等于(或大于)corePoolSize,则将任务放入队列。
    • 如果队列已满,并且线程数小于 maxPoolSize,则创建一个新线程来运行任务。
    • 如果队列已满,且线程数大于等于 maxPoolSize,则拒绝该任务。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 2014-04-28
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      相关资源
      最近更新 更多