Java 不阻塞的有界阻塞队列

Java 不阻塞的有界阻塞队列,java,blockingqueue,Java,Blockingqueue,这个问题的标题让我怀疑这是否存在,但仍然: 我感兴趣的是是否有Java的实现,它受大小限制,从不阻塞,而是在尝试将太多元素排队时抛出异常 编辑-我正在将BlockingQueue传递给一个执行者,我想它使用它的add方法,而不是offer。您可以编写一个BlockingQueue来包装另一个BlockingQueue,并将呼叫委托给AddtoOffer。编辑:根据您的新描述,我相信您问的问题是错误的。如果您使用的是执行器,您可能应该定义一个自定义队列,而不是修改队列。这仅在您使用ThreadPo

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

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

编辑-我正在将BlockingQueue传递给一个执行者,我想它使用它的add方法,而不是offer。您可以编写一个BlockingQueue来包装另一个BlockingQueue,并将呼叫委托给AddtoOffer。

编辑:根据您的新描述,我相信您问的问题是错误的。如果您使用的是执行器,您可能应该定义一个自定义队列,而不是修改队列。这仅在您使用ThreadPoolExecutor时有效,但如果您不使用ThreadPoolExecutor,则最好修改执行器而不是队列

我的观点是,否决报价并使其表现得像add是错误的。接口方法构成合同。使用阻塞队列的客户端代码取决于实际执行文档指定操作的方法。打破这条规则会带来伤害。这是不雅的

BlockingQueues上的方法可以做到这一点,但他们也有一种方法,通常是更好的选择。从报价文件中:

在指定的位置插入指定的元素 如果可能,此队列的尾部 立即这样做而不超过 队列的容量,返回true 如果此队列 已经满了。这种方法通常是可行的 优于方法addE,该方法可以 无法仅通过以下方式插入元素: 正在引发异常

这适用于所有此类队列,而不考虑具体的实现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
编辑:根据你的新描述,我相信你问错了问题。如果您使用的是执行器,您可能应该定义一个自定义队列,而不是修改队列。这仅在您使用ThreadPoolExecutor时有效,但如果您不使用ThreadPoolExecutor,则最好修改执行器而不是队列

我的观点是,否决报价并使其表现得像add是错误的。接口方法构成合同。使用阻塞队列的客户端代码取决于实际执行文档指定操作的方法。打破这条规则会带来伤害。这是不雅的

BlockingQueues上的方法可以做到这一点,但他们也有一种方法,通常是更好的选择。从报价文件中:

在指定的位置插入指定的元素 如果可能,此队列的尾部 立即这样做而不超过 队列的容量,返回true 如果此队列 已经满了。这种方法通常是可行的 优于方法addE,该方法可以 无法仅通过以下方式插入元素: 正在引发异常

这适用于所有此类队列,而不考虑具体的实现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
可以编写一个BlockingQueue 包装另一个BlockingQueue并 代表们要求添加到报价中

如果这是一个问题。。。答案是肯定的,但是您可以通过创建一个覆盖add的子类来更灵活地完成。在这两种情况下,唯一的问题是您的add版本不能抛出任何不在您要重写的方法中的已检查异常,因此您的将阻止异常将需要取消检查

可以编写一个BlockingQueue 包装另一个BlockingQueue并 代表们要求添加到报价中


如果这是一个问题。。。答案是肯定的,但是您可以通过创建一个覆盖add的子类来更灵活地完成。在这两种情况下,唯一的问题是,您的add版本无法抛出任何不在您要覆盖的方法中的已检查异常,因此您的Wild block异常将需要取消检查。

这很遗憾,您无法阻止,有太多的用例需要阻止,向执行者提供自己的有界阻塞队列的整个想法没有任何意义

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
        }
    }

这是可悲的,你不能阻止,有这么多的用例你想阻止,整个想法提供你自己的有界阻塞队列给执行者没有意义

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
        }
    }

这是一个简单的用例,可以在batch executor中从源数据库执行查询,在batch executor中丰富查询并将其放入另一个db executor,您可能希望执行查询的速度与将查询放入另一个db的速度一样快。在这种情况下,dest执行器应该接受一个阻塞有界执行器来解决问题,而不是保持轮询并检查完成了多少以执行更多查询


oops更多信息,请参见我的剩余注释:

一个简单的用例,用于在批处理执行器中从源数据库执行查询,在批处理中进行充实并放入另一个数据库执行器,您希望执行查询的速度与放入另一个数据库的速度一样快。其中 在这种情况下,dest执行器应该接受一个阻塞有界执行器来解决问题,而不是保持轮询并检查完成了多少以执行更多查询


更详细地说,请参见我的余数注释:

问题在于,您的子类的add方法现在的行为与基类的add不同-因此违反了替换原则。@Visage:是的,但有时您必须稍微违反一些好的设计原则才能使事情正常进行。在本例中,我期望并希望作者确保在非常狭窄的上下文中使用这个非标准类。当然,在公共API中公开它是个坏主意。问题是,子类的add方法现在的行为与基类的add方法不同,因此违反了替换原则。@Visage:是的,但有时为了使事情正常运行,您必须稍微违反一些好的设计原则。在本例中,我期望并希望作者确保在非常狭窄的上下文中使用这个非标准类。当然,在公共API中公开它是个坏主意。