【问题标题】:ThreadPoolExecutor#getPoolSize() vs ThreadPoolExecutor#getActiveCount() what is the differenceThreadPoolExecutor#getPoolSize() 与 ThreadPoolExecutor#getActiveCount() 有什么区别
【发布时间】:2020-08-12 12:40:07
【问题描述】:

我一直在玩ThreadPoolExecutor。我需要一个返回当前正在运行的线程数的方法。所以我决定使用ThreadPoolExecutor#getActiveCount

但是,当我测试我的方法时,我发现了一些有趣的东西:ThreadPoolExecutor#getActiveCount 总是等于 ThreadPoolExecutor#getPoolSize

这是一个重现它的示例代码:

class ExecutorTest {

        private ThreadPoolExecutor executor;

        ExecutorTest() {
            executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        }

        @Test
        void test() {
            executor.execute(makeRunnable(100, "1"));
            printExecutorState();
            executor.execute(makeRunnable(100, "2"));
            printExecutorState();
            executor.execute(makeRunnable(100, "3"));
            printExecutorState();
            executor.execute(makeRunnable(100, "4"));
            printExecutorState();

            System.out.println("==Changing thread core&max pool size==");
            executor.setCorePoolSize(2);
            executor.setMaximumPoolSize(2);

            printExecutorState();
            assertThat(executor.getMaximumPoolSize()).isEqualTo(2);
            assertThat(executor.getActiveCount()).isEqualTo(4);
        }

        private Runnable makeRunnable(long workTime, String name) {
            return () -> {
                long startTime = System.currentTimeMillis();
                System.out.println("Running " + name);
                while (System.currentTimeMillis() - startTime < workTime) {
                }
                System.out.println("Exited " + name);
            };
        }

        private void printExecutorState() {
            int poolSize = executor.getPoolSize();
            int corePoolSize = executor.getCorePoolSize();
            int maxPoolSize = executor.getMaximumPoolSize();
            int running = executor.getActiveCount();

            String currentState = String.format(
                    "poolSize=%d, corePoolSize=%d, maxPoolSize=%d, running=%d",
                    poolSize,
                    corePoolSize,
                    maxPoolSize,
                    running
            );

            System.out.println(currentState);
        }
    }

它打印以下内容:

Running 1
poolSize=1, corePoolSize=10, maxPoolSize=10, running=1
Running 2
poolSize=2, corePoolSize=10, maxPoolSize=10, running=2
Running 3
poolSize=3, corePoolSize=10, maxPoolSize=10, running=3
Running 4
poolSize=4, corePoolSize=10, maxPoolSize=10, running=4
==Changing thread core&max pool size==
poolSize=4, corePoolSize=2, maxPoolSize=2, running=4

现在的问题是这些方法之间有什么区别?使用ThreadPoolExecutor#getPoolSize 来检索正在运行的线程数有意义吗?

【问题讨论】:

    标签: java multithreading threadpoolexecutor


    【解决方案1】:

    如果你只是看一下 javadoc 的功能,你会得到不同的:

    /**
    * Returns the current number of threads in the pool.
    *
    * @return the number of threads
    */
    public int getPoolSize() 
    
    /**
    * Returns the approximate number of threads that are actively
    * executing tasks.
    *
    * @return the number of threads
    */
    public int getActiveCount()
    

    池中且未执行任何任务的线程将包含在 getPoolSize() 中,但不包含在 getActiveCount() 中。在您的初始代码中,您创建了池大小为 10 的线程池,但提交了 4 个任务。因此池大小为 10,活动计数为 4。因此,使用 ThreadPoolExecutor#getPoolSize 检索正在运行的线程数是错误。它只是为您提供创建的线程数,活动运行的线程数由活动计数给出。

    在您的用例中,请注意即使将最大池大小减小到 2,池大小仍为 4。所以发生的情况是 4 个线程正在执行 4 个任务。

    完成任务的前两个线程将终止。届时,池大小将减少到 2,而 active 仍为 2(其他任务正在进行中)。

    当其他两个线程完成它们的任务时,池大小将保持为 2(核心池大小),但由于没有任务在运行,因此活动将恢复为 0。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-17
      • 2011-04-30
      • 1970-01-01
      • 2016-07-08
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      相关资源
      最近更新 更多