1

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

我对是否有 Java 的BlockingQueue的实现感兴趣,它受大小限制,从不阻塞,而是在尝试将太多元素排入队列时抛出异常。

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

4

4 回答 4

4

编辑:根据您的新描述,我相信您问错了问题。如果您使用的是 Executor,您可能应该定义一个自定义RejectedExecutionHandler而不是修改队列。这仅在您使用 ThreadPoolExecutor 时有效,但如果您不是,那么修改 Executor 而不是队列可能是一个更好的主意。

我认为覆盖 offer 并使其表现得像 add 是错误的。接口方法构成契约。使用阻塞队列的客户端代码取决于实际执行文档指定的方法。打破这条规则会打开一个受伤的世界。那,而且很不雅。


BlockingQueues 上的add()方法可以做到这一点,但它们也有一个offer()方法,这通常是更好的选择。来自 offer() 的文档:

如果可以在不超过队列容量的情况下立即插入,则在此队列的尾部插入指定元素,成功时返回 true,如果队列已满则返回 false。此方法通常比方法 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
于 2009-08-05T05:40:29.603 回答
0

可以编写一个 BlockingQueue 包装另一个 BlockingQueue 并将 add() 的调用委托给 offer()。

如果这应该是一个问题……答案是“是”,但是您可以通过创建一个覆盖 add() 的子类来更巧妙地做到这一点。唯一的问题(在这两种情况下)是您的版本add不能抛出任何不在您正在覆盖的方法中的检查异常,因此您的“将阻止”异常需要取消检查。

于 2009-08-05T07:48:24.137 回答
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
        }
    }
于 2010-10-22T04:11:30.367 回答
0

一个简单的用例,用于从源数据库批量执行查询(执行程序),批量丰富并放入另一个数据库(执行程序),您可能希望仅在将查询放入另一个数据库时执行查询。在这种情况下,dest 执行器应该接受一个阻塞的有界执行器来解决问题,而不是继续轮询并检查有多少已完成以执行更多查询。

哎呀更多,请参阅我的剩余评论:

于 2010-10-22T04:35:40.650 回答