一个有限的BlockingQueue,它不会阻塞

时间:2009-08-05 05:36:52

标签: java blockingqueue

这个问题的标题让我怀疑这是否存在,但仍然存在:

我感兴趣的是Java是否实现了BlockingQueue,它是由大小限制的,并且从不阻塞,而是在尝试排队太多元素时引发异常。

编辑 - 我正在将BlockingQueue传递给Executor,我认为它使用的是add()方法,而不是offer()。可以写一个封装另一个BlockingQueue的BlockingQueue,并将add()的调用委托给offer()。

4 个答案:

答案 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,请参阅余下的评论: