ThreadPoolExecutor#getPoolSize() 与 ThreadPoolExecutor#getActiveCount() 之间的区别是什么?

huangapple go评论159阅读模式
英文:

ThreadPoolExecutor#getPoolSize() vs ThreadPoolExecutor#getActiveCount() what is the difference

问题

ThreadPoolExecutor#getPoolSize and ThreadPoolExecutor#getActiveCount are two methods in Java's ThreadPoolExecutor class used for managing and monitoring thread pools. Here's the difference between them:

  1. ThreadPoolExecutor#getPoolSize:

    • This method returns the current size of the thread pool, which is the total number of threads that have been created and are currently in the pool.
    • It includes both active (running) threads and idle threads waiting to execute tasks.
    • It doesn't give you the exact count of currently running threads; it gives you the total pool size, including those waiting for tasks.
  2. ThreadPoolExecutor#getActiveCount:

    • This method returns the approximate number of threads that are actively executing tasks.
    • It provides a count of the threads that are currently running tasks and excludes idle threads.
    • It is designed to give you a more accurate count of the currently running threads.

In your code and output, you can see that ThreadPoolExecutor#getPoolSize gives you the total pool size, which includes both running and idle threads, whereas ThreadPoolExecutor#getActiveCount gives you the count of actively running threads.

For most cases where you need to know the number of running threads, it makes more sense to use ThreadPoolExecutor#getActiveCount because it provides a more accurate count of currently executing threads. Using ThreadPoolExecutor#getPoolSize may not accurately reflect the number of active threads, especially if there are idle threads in the pool.

英文:

I've been playing with ThreadPoolExecutor. I needed a method that returns the number of threads which are currently running. So I decided to use ThreadPoolExecutor#getActiveCount.

However, when I was testing my methods I noticed something interesting: ThreadPoolExecutor#getActiveCount is always equal to ThreadPoolExecutor#getPoolSize.

Here is a sample code to reproduce it:

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);
        }
    }

It prints the following:

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

Now the question is what is the difference between these methods? Does it make sense to use ThreadPoolExecutor#getPoolSize to retrieve number of running threads?

答案1

得分: 1

以下是翻译好的部分:

"你只需查看函数的javadoc,就可以明显看出差异:

/**
* 返回池中当前线程数。
*
* @return 线程数
*/
public int getPoolSize() 

/**
* 返回活动执行任务的线程数的近似值。
*
* @return 线程数
*/
public int getActiveCount()

在池中并且没有执行任何任务的线程将包括在getPoolSize()中,但不包括在getActiveCount()中。在你的初始代码中,你创建了池大小为10的线程池,但提交了4个任务。因此,池大小为10,活动计数为4。因此,使用ThreadPoolExecutor#getPoolSize来检索运行线程的数量是错误的。它只会给你创建的线程数量,实际运行线程的数量由活动计数给出。

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

首先完成其任务的前两个线程将终止。在那时,池大小将减小到2,但仍然是2(其他任务正在进行中)。

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

英文:

You can get the difference if you simply look at javadoc for the functions:

/**
* 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()

A thread that is in the pool and not executing any task will be included getPoolSize() but not in getActiveCount(). In your initial code, you created thread pool with pool size 10, but submitted 4 tasks. Hence pool size was 10 and active count was 4. So use of ThreadPoolExecutor#getPoolSize to retrieve number of running threads is wrong. It just gives you the number of threads created, the number of actively running threads is given by active count.

In your use case, notice how the pool size is still 4 even after reducing max pool size to 2. So what is happening is 4 threads are executing 4 tasks.

First two threads that complete their task will terminate. At that point, pool size will be reduced to 2 and active will still be 2 (other tasks in progress).

When other two threads complete their task, pool size will remain 2 (core pool size) but active will revert to 0 since no tasks are running.

huangapple
  • 本文由 发表于 2020年8月12日 20:40:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/63376734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定