这个问题的标题让我怀疑这是否存在,但仍然存在:
我感兴趣的是Java是否实现了BlockingQueue,它是由大小限制的,并且从不阻塞,而是在尝试排队太多元素时引发异常。
编辑 - 我正在将BlockingQueue传递给Executor,我认为它使用的是add()方法,而不是offer()。可以写一个封装另一个BlockingQueue的BlockingQueue,并将add()的调用委托给offer()。
答案 0 :(得分:4)
修改:根据您的新描述,我相信您提出了错误的问题。如果您正在使用Executor,则应该定义自定义RejectedExecutionHandler而不是修改队列。这仅在您使用ThreadPoolExecutor时有效,但如果您不是,那么修改Executor而不是队列可能更好。
我认为,覆盖优惠并使其行为像添加一样是错误的。接口方法构成合同。使用阻塞队列的客户端代码取决于实际执行文档指定的方法。打破这个规则打开了一个受伤的世界。那,而且它不够优雅。
BlockingQueues上的add()方法可以做到这一点,但它们也有offer()方法,这通常是更好的选择。来自offer()的文档:
在指定元素处插入 如果可能的话,这个队列的尾部 立即这样做,不要超过 队列的容量,返回true 成功后如果这个队列是假的 已满。这种方法一般 优选方法add(E),可以 无法仅插入元素 抛出异常。
这适用于所有此类队列,无论具体实现如何(ArrayBlockingQueue,LinkedBlockingQueue等)
BlockingQueue<String> q = new LinkedBlockingQueue<String>(2);
System.out.println(q.offer("foo")); // true
System.out.println(q.offer("bar")); // true
System.out.println(q.offer("baz")); // false
答案 1 :(得分:0)
可以写一个BlockingQueue 包装另一个BlockingQueue和 委托调用add()to offer()。
如果这应该是一个问题...答案是“是”,但你可以通过创建一个覆盖add()的子类来更加整洁地完成它。唯一的问题是(在这两种情况下)你的add
版本不会抛出任何不在你覆盖的方法中的已检查异常,因此需要取消选中“阻止”异常。
答案 2 :(得分:0)
这很难过,你无法阻止,有很多你想要阻止的用例,为执行者提供你自己的有界阻塞队列的整个想法没有意义。
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
if (runState == RUNNING && workQueue.***offer***(command)) {
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
else if (!addIfUnderMaximumPoolSize(command))
reject(command); // is shutdown or saturated
}
}
答案 3 :(得分:0)
一个简单的用例,用于在批处理(执行程序)中从源数据库执行查询,丰富批处理并放入另一个数据库(执行程序),您只希望执行查询的速度与放入另一个数据库的速度一样快。在这种情况下,dest执行程序应该接受一个阻塞有界执行程序来解决问题,而不是继续轮询并检查完成执行更多查询的数量。
oops more,请参阅余下的评论: