有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java ThreadPoolExecutor#getPoolSize()与ThreadPoolExecutor#getActiveCount()有什么区别

我一直在玩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检索正在运行的线程数有意义吗


共 (1) 个答案

  1. # 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,活动池大小仍将为2(其他正在进行的任务)

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