Есть очередь задач, создана следующим образом:
LinkedBlockingQueue
Значение maximumPoolSize равно 200. Во время работы в queue попадает большое количество потоков (больше тысячи), но значение, возвращаемое методом threadPoolExecutor.getActiveCount() всегда меньше либо равно 100. Например, значения threadPoolExecutor.getActiveCount() и queue.size() логируются следующим образом:
logger.debug("Активные потоки: " + threadPoolExecutor.getActiveCount() + ". В очереди " + queue.size() + " потоков.");
и в итоге мы получаем следующую картину:
Активные потоки: 1. В очереди 0 потоков.
Активные потоки: 2. В очереди 0 потоков.
Активные потоки: 3. В очереди 0 потоков.
Активные потоки: 4. В очереди 0 потоков.
Активные потоки: 5. В очереди 0 потоков.
...
Активные потоки: 86. В очереди 0 потоков.
Активные потоки: 87. В очереди 1 потоков.
Активные потоки: 88. В очереди 1 потоков.
Активные потоки: 89. В очереди 1 потоков.
Активные потоки: 90. В очереди 1 потоков.
...
Активные потоки: 99. В очереди 1 потоков.
Активные потоки: 100. В очереди 1 потоков.
Активные потоки: 100. В очереди 2 потоков.
Активные потоки: 100. В очереди 3 потоков.
Активные потоки: 100. В очереди 4 потоков.
...
Активные потоки: 100. В очереди 1874 потоков.
Активные потоки: 100. В очереди 1875 потоков.
Активные потоки: 100. В очереди 1876 потоков.
Активные потоки: 100. В очереди 1877 потоков.
Активные потоки: 100. В очереди 1878 потоков.
Активные потоки: 100. В очереди 1879 потоков.
Активные потоки: 100. В очереди 1880 потоков.
Активные потоки: 100. В очереди 1881 потоков.
Активные потоки: 100. В очереди 1882 потоков.
Активные потоки: 100. В очереди 1883 потоков.
В документации написано, что метод threadPoolExecutor.getActiveCount() возвращает приблизительное количество потоков с активно выполняющимися задачами. Но почему максимальный порог этого приблизительного значения тут равен maximumPoolSize/2?
P.S. Это логи не с моего компьютера, у меня такую ситуацию воспроизвести не удалось - у меня в данном случае количество активных потоков равняется 200, как и ожидалось. Может ли это быть зависимость от количества процессоров/количества ядер процессоров/какой-либо конфигурации ПО?
Ответ
"Есть очередь задач, создана следующим образом: ... new
ThreadPoolExecutor(maximumPoolSize, maximumPoolSize, .."
Вы уверены, что maximumPoolSize - это одна переменная, и она имеет одно значение? Полагаю, что причина в том, что corePoolSize равен 100, а maximumPoolSize равен 200 и у Вас происходит следующее?
При добавлении нового потока в пул выполняет следующие действия последовательно:
Проверяет достигнут ли предел потоков, задаваемых переменной
corePoolSize если можно еще запустить поток - запускает его. Если
количество потоков равно или больше corePoolSize переходит к
следующему шагу.
Проверяет не заполнена ли очередь и если в ней еще есть место
добавляет туда поток. Если очередь заполнена переходит к следующему
шагу.
Пытается увеличить количество работающих потоков до значения
maximumPoolSize если можно добавить еще поток, то он добавляется и в
нем и запускается задание. Если количество работающих потоков равно
maximumPoolSize то выбрасывается исключение
java.util.concurrent.RejectedExecutionException или вызывается
перехватчик отклонения задачи определяемый программистом.
В вашем случае в виду того, что очередь увеличивается без ограничений к третьему шагу алгоритм никогда не переходит. Но можно «изменить» порядок следования шагов 2 и 3. Для этого необходимо создать очередь в которой мы переопределим вызываемый ThreadPoolExecutor метод offer так, чтобы он возвращал всегда false (очередь заполнена). Теперь нам нужно задать собственный перехватчик RejectedExecutionHandler. В перехватчике мы добавляем полученный поток в очередь. Пример изложенного выше в виде кода:
LinkedBlockingQueue
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(100, 200,
1, TimeUnit.MINUTES,
queue,
new RejectedExecutionHandler() {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Комментариев нет:
Отправить комментарий