java ThreadPoolExecutor не может создать собственный поток

Мне нужно иметь глобальный пул потоков в моей системе для обработки заказов клиентов. Система основана на tomcat и должна принимать запросы клиентов 24/7. Я использовал ThreadPoolExecutor следующим образом:

 private ThreadPoolExecutor exec = new ThreadPoolExecutor(100, 1000, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue());

Но иногда моя система зависает с исключением: «OutOfMemory: невозможно создать новый собственный поток». Итак, вопросы: 1. Будут ли все отправленные потоки постоянно находиться в пуле до его закрытия? 2. Что я должен использовать для создания пула потоков, который может повторно использовать или очищать завершенные задачи, чтобы он никогда не зависал?

Я также добавил сообщение журнала перед pool.submit:

logger.info("Active count: "+pool.getActiveCount()+" completed: "+pool.getCompletedTaskCount());

Но активное количество всегда равно нулю. Почему? Java-версия — openJDK 8 на FreeBSD.


person avalon    schedule 29.11.2015    source источник
comment
1) вы читали документы docs.oracle.com/javase/7/docs/api/java/util/concurrent/ (только ядро ​​будет) ? Может быть, бассейн фиксированного размера? Действительно зависит. Вам нужно столько нитей? Ваша система имеет 1000 ядер и может выполнять 1000 операций параллельно?   -  person zapl    schedule 29.11.2015
comment
@zapl, если задачи связаны с вводом-выводом, то имеет смысл иметь пул размером больше, чем количество ядер.   -  person Sleiman Jneidi    schedule 29.11.2015
comment
@SleimanJneidi Тысяча тем — это много. Даже сотня потоков — это много. Независимо от того, на каком оборудовании будет работать служба, будут практические ограничения на количество одновременных клиентов и количество запросов в секунду, которые она может обрабатывать. Хитрость заключается в том, чтобы спроектировать систему, которая будет изящно деградировать под давлением, а не просто давать сбой из-за ошибки OOM.   -  person Solomon Slow    schedule 29.11.2015
comment
@jameslarge есть много людей, которые могут позволить себе машины с сотнями ядер и терабайтами памяти, может быть, ОП — один из них :)   -  person Sleiman Jneidi    schedule 29.11.2015
comment
@SleimanJneidi, хорошо, может быть, тысяча потоков всегда не так уж и много, но в системе ОП, по-видимому, не хватает потоков. Даже на самых больших серверах что-то закончится, если вы нажмете на них достаточно сильно, и хитрость по-прежнему заключается в том, чтобы изящно снижать производительность, не переходя черту, а не пересекая ее и не вылетая. Правильно настроенный пул потоков — это один из инструментов, который можно использовать для достижения этой цели.   -  person Solomon Slow    schedule 29.11.2015


Ответы (1)


Слишком много вещей может пойти не так, вот очевидные из них:

  1. maximumPoolSize имеет значение 1000, это магическое число, не связанное с аппаратным обеспечением, на котором работает программа.

  2. Back-pressure, вы используете LinkedBlockingQueue, который приветствует любую новую задачу, возможно, вам придется подумать об использовании ArrayBlockingQueue и поставить ему capacity.

настройка maximumPoolSize зависит от вашего приложения, ваши задачи compute bound? Тогда размер пула, превышающий количество ядер, доступных на производственной машине (не на машине разработки), не принесет вам ничего, кроме оплаты накладных расходов на переключение контекста и потребление памяти.

В Java есть очень полезный метод, который дает вам количество ядер, которые у вас есть, пожалуйста, используйте его.

Runtime.getRuntime().availableProcessors();  
person Sleiman Jneidi    schedule 29.11.2015
comment
Спасибо, но должен ли размер ядра быть равен количеству процессоров или просто N * число процессоров? Итак, если у меня 4 процессора, могу ли я указать размер ядра как 16, 32 или просто 4? Спасибо - person avalon; 29.11.2015
comment
@avalon опять же, это зависит от задач, задачи, связанные с вычислениями, сильно отличаются от задач, связанных с вводом-выводом. - person Sleiman Jneidi; 29.11.2015
comment
Задачи имеют дело с rabbitMQ+разные вычисления+groovy - person avalon; 29.11.2015
comment
Моя текущая проблема заключается в том, что потоки застряли в TPE, как будто они все еще живы, но getActiveCount всегда равен 0. - person avalon; 29.11.2015
comment
@avalon Я считаю, что groovy — это язык, а не задача - person Sleiman Jneidi; 29.11.2015
comment
Да, извините, я просто пытался объяснить. Задачи смешанные - ввод-вывод+вычисления. - person avalon; 29.11.2015
comment
@avalon взгляните на этот infoq.com/articles/Java-Thread -Настройка производительности пула - person Sleiman Jneidi; 29.11.2015