Почему всегда threadPoolExecutor.getActiveCount() ‹= maxPoolSize/2?

У нас есть очередь задач и ее инициализация выглядит так:

LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(maximumPoolSize, maximumPoolSize, 50000L, TimeUnit.MILLISECONDS, queue);

Значение maximumPoolSize равно 200. При работе очередь получает большое количество потоков (более тысячи), но значение, возвращаемое threadPoolExecutor.getActiveCount(), всегда меньше или равно 100. Например, значения threadPoolExecutor.getActiveCount() и queue.size() регистрируются следующим образом :

logger.debug("Active threads: " + threadPoolExecutor.getActiveCount() + ".  The queue has " + queue.size() + " threads.");

и в результате получаем следующий лог:

Active threads: 1. The queue has 0 threads.
Active threads: 2. The queue has 0 threads.
Active threads: 3. The queue has 0 threads.
Active threads: 4. The queue has 0 threads.
Active threads: 5. The queue has 0 threads.
...
Active threads: 86. The queue has 0 threads.
Active threads: 87. The queue has 1 threads.
Active threads: 88. The queue has 1 threads.
Active threads: 89. The queue has 1 threads.
Active threads: 90. The queue has 1 threads.
...
Active threads: 99. The queue has 1 threads.
Active threads: 100. The queue has 1 threads.
Active threads: 100. The queue has 2 threads.
Active threads: 100. The queue has 3 threads.
Active threads: 100. The queue has 4 threads.
...
Active threads: 100. The queue has 1874 threads.
Active threads: 100. The queue has 1875 threads.
Active threads: 100. The queue has 1876 threads.
Active threads: 100. The queue has 1877 threads.
Active threads: 100. The queue has 1878 threads.
Active threads: 100. The queue has 1879 threads.
Active threads: 100. The queue has 1880 threads.
Active threads: 100. The queue has 1881 threads.
Active threads: 100. The queue has 1882 threads.
Active threads: 100. The queue has 1883 threads.

В документах говорится, что метод threadPoolExecutor.getActiveCount()

возвращает приблизительное количество потоков, активно выполняющих задачи

Но почему максимальный порог этого приблизительного значения всегда равен maximumPoolSize/2? Это должно быть так?

P.S. Я не мог воспроизвести эту ситуацию: на моем ПК в этом случае всегда было 200 активных потоков. Но приведенные выше журналы не с моего компьютера. Может это зависит от количества процессоров/виртуальных ядер?

Я также нашел интересный фрагмент кода в Серый блог< /а>:

int cpus = Runtime.getRuntime().availableProcessors(); 
int maxThreads = cpus * scaleFactor; 
maxThreads = (maxThreads > 0 ? maxThreads : 1);

Но в конце концов я очень запутался, потому что значение Runtime.getRuntime().availableProcessors() на моем ПК равно 8.


person Ksenia    schedule 23.02.2016    source источник
comment
Примечание: если у вас нет такого количества логических процессоров, вы можете обнаружить, что большее количество потоков работает медленнее, хотя похоже, что вы установили максимум на 100, как предлагает @VickyThakor.   -  person Peter Lawrey    schedule 23.02.2016
comment
@PeterLawrey, я отредактировал свой пост   -  person Ksenia    schedule 23.02.2016
comment
Я предлагаю вам напечатать threadPoolExecutor.getPoolSize() Максимум не зависит от количества ядер, которые у вас есть, а только от точки, в которой не рекомендуется иметь больше.   -  person Peter Lawrey    schedule 23.02.2016
comment
Добавьте в логи threadPoolExecutor.getMaximumPoolSize(), чтобы убедиться, что maximumPoolSize действительно 200.   -  person Roman    schedule 26.02.2016


Ответы (1)


Вы уверены, что переменная maximumPoolSize имеет значение 200. Он отлично работает на моем конце.

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class SO35570728 {

    private class Task implements Runnable{

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " started");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " finished");
        }
    }

    public static void main(String[] args) {
        LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(200, 200, 50000L, TimeUnit.MILLISECONDS, queue);

        for(int i= 0 ; i < 100000 ; i++){
            System.out.println("Active threads: " + threadPoolExecutor.getActiveCount() + ".  The queue has " + queue.size() + " threads.");
            threadPoolExecutor.submit(new SO35570728().new Task());
        }
    }
}

Выход

Active threads: 0.  The queue has 0 threads.
Active threads: 1.  The queue has 0 threads.
Active threads: 2.  The queue has 0 threads.
Active threads: 3.  The queue has 0 threads.
...
pool-1-thread-1 started
pool-1-thread-2 started
pool-1-thread-3 started
...
Active threads: 200.  The queue has 99793 threads.
Active threads: 200.  The queue has 99794 threads.
Active threads: 200.  The queue has 99795 threads.
Active threads: 200.  The queue has 99796 threads.
Active threads: 200.  The queue has 99797 threads.
Active threads: 200.  The queue has 99798 threads.
Active threads: 200.  The queue has 99799 threads.
person Vicky Thakor    schedule 23.02.2016