[首先,我道歉,这是对之前答案的回应,但我想要格式化]。
但实际上,当将项目提交到队列已满的 ThreadPoolExecutor 时,您不会阻塞。原因是 ThreadPoolExecutor 调用 BlockingQueue.offer(T item) 方法,根据定义,该方法是非阻塞方法。它要么添加项目并返回 true,要么不添加(满时)并返回 false。然后ThreadPoolExecutor调用注册的RejectedExecutionHandler来处理这种情况。
来自javadoc:
在将来的某个时间执行给定的任务。任务可能会执行
在新线程或现有池线程中。如果任务无法完成
提交执行,要么因为这个执行者已经
关闭或因为其容量已达到,任务已处理
由当前的 RejectedExecutionHandler 执行。
默认情况下,使用 ThreadPoolExecutor.AbortPolicy(),它会从 ThreadPoolExecutor 的“submit”或“execute”方法抛出 RejectedExecutionException。
try {
executorService.execute(new Runnable() { ... });
}
catch (RejectedExecutionException e) {
// the queue is full, and you're using the AbortPolicy as the
// RejectedExecutionHandler
}
但是,您可以使用其他处理程序执行不同的操作,例如忽略错误(DiscardPolicy),或在调用“execute”或“submit”方法(CallerRunsPolicy)的线程中运行它。此示例允许调用“提交”或“执行”方法的线程在队列已满时运行请求的任务。 (这意味着在任何给定时间,您都可以在池本身的基础上运行 1 个额外的东西):
ExecutorService service = new ThreadPoolExecutor(..., new ThreadPoolExecutor.CallerRunsPolicy());
如果您想阻塞并等待,您可以实现自己的 RejectedExecutionHandler ,它将阻塞直到队列上有可用的插槽(这是一个粗略的估计,我还没有编译或运行它,但您应该明白这个想法):
public class BlockUntilAvailableSlot implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (e.isTerminated() || e.isShutdown()) {
return;
}
boolean submitted = false;
while (! submitted) {
if (Thread.currentThread().isInterrupted()) {
// be a good citizen and do something nice if we were interrupted
// anywhere other than during the sleep method.
}
try {
e.execute(r);
submitted = true;
}
catch (RejectedExceptionException e) {
try {
// Sleep for a little bit, and try again.
Thread.sleep(100L);
}
catch (InterruptedException e) {
; // do you care if someone called Thread.interrupt?
// if so, do something nice here, and maybe just silently return.
}
}
}
}
}