【问题标题】:Block before draining ArrayBlockingQueue在排空 ArrayBlockingQueue 之前阻塞
【发布时间】:2013-03-04 00:32:19
【问题描述】:

我发现自己在重复这种模式,并且经常想知道它是否在 Java 中是惯用的,或者有更好的方法来实现这种行为。

问题:给定生产者/消费者设置,消费者想要处理批量项目,因此它使用drainTo(),但是drainTo() 将轮询现有项目并且可能无法获取任何项目,以避免这个 I 前缀使用take() 确保它在至少有一件物品可用之前阻塞。

对于特定数据集,我遇到的一个问题是,在许多用例中,批量大小通常在 (1, N, 1, N) 之间交替出现不规则。一般来说,这是解决此问题的常用方法:

例子:

 ArrayBlockingQueue<Foo> queue;

 function void produce() {
    while(true) {
       queue.put(createFoo());
    }
 }

 function void consumeBatchSpin() {
    while(true) {
       List<Foo> batch = Lists.newLinkedList();
       queue.drainTo(batch);

       doSomething(batch);
       //the problem here is that if nothing is being produced, this loop will spin
    }
 }

 function void consumeBatchTake() {
    while(true) {
       List<Foo> batch = Lists.newLinkedList();
       batch.add(queue.take()); //force at least one item to be there
       queue.drainTo(batch);

       doSomething(batch);
    }
 }

【问题讨论】:

标签: java concurrency


【解决方案1】:

您是否考虑过添加到列表中并在获取时获取整个列表。

我最近发布了一个here。它正在进行代码审查here,但我的测试表明它很强大。

基本上,当您执行 put 时,您会将新元素添加到当前列表中。当您执行 get 时,您将获得 整个 列表并自动将其替换为新的空列表。

无需使用drainTo,完全无需旋转。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多