🛠️ ThreadPoolExecutor saturated, а CPU ещё не 100%?
Это возможно: threads могут ждать database, HTTP, filesystem, locks или другой blocking dependency.
Для execute() логика такая:
threads < corePoolSize
→ новый thread
core достигнут
→ сначала queue
queue не принимает
→ threads растут до maximumPoolSize
queue не принимает + pool at max
→ RejectedExecutionHandler
Отсюда важная ловушка.
corePoolSize = 10
maximumPoolSize = 100
queue = new LinkedBlockingQueue()
Без заданной capacity такая queue практически неограниченная.
После загрузки core threads задачи будут накапливаться в queue, а pool обычно не вырастет до 100.
Поэтому увеличение maximumPoolSize может ничего не изменить.
С bounded queue executor после её заполнения может расти выше core — до max.
Но bounded queue сама по себе overload не решает: нужна понятная rejection/backpressure strategy.
RejectedExecutionException тоже не обязательна.
Её бросает AbortPolicy; другая policy может вести себя иначе.
Перед tuning соберите:
— core/max pool size;
— poolSize и approximate activeCount;
— тип и capacity queue;
— incoming и completed rate;
— task latency;
— rejection policy;
— downstream latency.
Главный вопрос:
это временный burst
или
incoming rate стабильно выше completion rate?
Во втором случае большая queue только откладывает проблему.
Сохраните параметры, которые нужно собрать до изменения размера thread pool.
😄VK | 💬Макс | 🌐 Cайт
🔹🔹🔹🔹
Это возможно: threads могут ждать database, HTTP, filesystem, locks или другой blocking dependency.
Для execute() логика такая:
threads < corePoolSize
→ новый thread
core достигнут
→ сначала queue
queue не принимает
→ threads растут до maximumPoolSize
queue не принимает + pool at max
→ RejectedExecutionHandler
Отсюда важная ловушка.
corePoolSize = 10
maximumPoolSize = 100
queue = new LinkedBlockingQueue()
Без заданной capacity такая queue практически неограниченная.
После загрузки core threads задачи будут накапливаться в queue, а pool обычно не вырастет до 100.
Поэтому увеличение maximumPoolSize может ничего не изменить.
С bounded queue executor после её заполнения может расти выше core — до max.
Но bounded queue сама по себе overload не решает: нужна понятная rejection/backpressure strategy.
RejectedExecutionException тоже не обязательна.
Её бросает AbortPolicy; другая policy может вести себя иначе.
Перед tuning соберите:
— core/max pool size;
— poolSize и approximate activeCount;
— тип и capacity queue;
— incoming и completed rate;
— task latency;
— rejection policy;
— downstream latency.
Главный вопрос:
это временный burst
или
incoming rate стабильно выше completion rate?
Во втором случае большая queue только откладывает проблему.
Сохраните параметры, которые нужно собрать до изменения размера thread pool.
😄VK | 💬Макс | 🌐 Cайт
🔹🔹🔹🔹