Я решил эту проблему с помощью пользовательского RejectedExecutionHandler, который просто на некоторое время просто блокирует вызывающий поток, а затем снова пытается отправить задачу:
public class BlockWhenQueueFull implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// The pool is full. Wait, then try again.
try {
long waitMs = 250;
Thread.sleep(waitMs);
} catch (InterruptedException interruptedException) {}
executor.execute(r);
}
}
Этот класс можно просто использовать в потоке.Исполнитель пула как RejectedExecutionHandler, как и любой другой.В этом примере:
executorPool = new def threadPoolExecutor = new ThreadPoolExecutor(3, 3, 1L, TimeUnit.HOURS, workQueue, new BlockWhenQueueFull())
Единственным недостатком, который я вижу, является то, что вызывающий поток может быть заблокирован немного дольше, чем это строго необходимо (до 250 мс).Для многих краткосрочных задач, возможно, уменьшите время ожидания до 10 мс или около того.Более того, поскольку этот исполнитель фактически вызывается рекурсивно, очень долгое ожидание появления потока (часы) может привести к переполнению стека.
Тем не менее мне лично нравится этот метод.Он компактен, прост для понимания и хорошо работает.Я что-то упустил? 1009 *