Мне нужно реализовать пул потоков в Java (java.util.concurrent), число потоков которого при некотором минимальном значении равно нулю, растет до верхней границы (но не более), когда задания отправляются в него быстрее, чем они заканчивают выполнение и сжимаются до нижней границы, когда выполняются все задания, и больше не представлено заданий.
Как бы вы реализовали что-то подобное? Я предполагаю, что это будет довольно распространенный сценарий использования, но, по-видимому, методы java.util.concurrent.Executors
factory могут создавать только пулы и пулы с фиксированным размером, которые неограниченно растут при подаче многих заданий. Класс ThreadPoolExecutor
предоставляет параметры corePoolSize
и maximumPoolSize
, но его документация, по-видимому, подразумевает, что единственный способ иметь больше потоков corePoolSize
в то же время - использовать ограниченную очередь заданий, в этом случае, если вы достигли потоков maximumPoolSize
, вы получите отказ от работы, с которым вам приходится иметь дело? Я придумал это:
//pool creation
ExecutorService pool = new ThreadPoolExecutor(minSize, maxSize, 500, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(minSize));
...
//submitting jobs
for (Runnable job : ...) {
while (true) {
try {
pool.submit(job);
System.out.println("Job " + job + ": submitted");
break;
} catch (RejectedExecutionException e) {
// maxSize jobs executing concurrently atm.; re-submit new job after short wait
System.out.println("Job " + job + ": rejected...");
try {
Thread.sleep(300);
} catch (InterruptedException e1) {
}
}
}
}
Я что-то пропускаю? Есть лучший способ сделать это? Кроме того, в зависимости от одного из требований может быть проблематично, что приведенный выше код не будет завершен до тех пор, пока, по крайней мере, (я думаю) не завершает работу (total number of jobs) - maxSize
. Поэтому, если вы хотите отправить произвольное количество заданий в пул и продолжить немедленно, не дожидаясь окончания какого-либо из них, я не вижу, как вы могли бы это сделать, не имея выделенного потока работы, который управляет требуемую неограниченную очередь для хранения всех представленных заданий. AFAICS, если вы используете неограниченную очередь для самого ThreadPoolExecutor, его количество потоков никогда не будет расти за пределы corePoolSize.