java 7/8中带有大小限制的linkedtransfer队列的任何替代方案?

问题描述 投票:1回答:4

为了实现生产者/消费者模式,我使用了LinkedTransferQueue

检查以下代码

while (true) {

    String tmp = new randomString();
    if (linkedTransferQueueString.size() < 10000) {
        linkedTransferQueueString.add(tmp);             
        }

}

从文档中,它指出大小是O(n)操作:(。因此,对于添加元素,它应该遍历整个集合。

是否有任何其他并发收集队列有大小限制?在java standard collectionsapache concurrent collections找不到任何东西?

java apache-commons java.util.concurrent
4个回答
1
投票

BlockingQueue

BlockingQueue implementations are thread-safe

[...]

BlockingQueue可以是容量限制的。

ArrayBlockingQueue

A bounded blocking queue backed by an array

以下是您用它编写示例的方法:

BlockingQueue queue = new ArrayBlockingQueue<>(10000);
while (true) {
    String tmp = new randomString();
    if (!queue.offer(tmp)) {
        // the limit was reached, item was not added
    }
}

或者对于简单的生产者/消费者示例

public static void main(String[] args) {
    // using a low limit so it doesn't take too long for the queue to fill
    BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);

    Runnable producer = () -> {
        if (!queue.offer(randomString())) {
            System.out.println("queue was full!");
        }
    };
    Runnable consumer = () -> {
        try {
            queue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    };
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);
    // produce faster than consume so the queue becomes full eventually
    executor.scheduleAtFixedRate(producer, 0, 100, TimeUnit.MILLISECONDS);
    executor.scheduleAtFixedRate(consumer, 0, 200, TimeUnit.MILLISECONDS);
}

2
投票

@OP:你已经接受了答案并且它也是正确的,但你仍然提高了赏金,所以我假设你更多地寻找这个概念,所以我只是对这个部分进行说明。

现在,您的问题是您对O(n)的尺寸操作不满意,这意味着您的解决方案是:

  • 数据结构应该能够告诉您队列已满。
  • 大小操作应该以恒定的时间返回结果。

大小操作给O(n)并不常见但是因为在LinkedTransferQueue的情况下存在异步行为,所以遍历完整队列以确保队列中的元素数量。否则,大多数队列实现会在恒定时间内为您提供大小结果,但您实际上不需要进行此大小检查,请继续阅读。

如果你对LinkedTransferQueue的目的有很强的依赖性,即你想根据某个生产者队列中队列的长度而出队,那么我认为除了你可以做一些像扩展LinkedTransferQueue这样的脏东西之外别无选择然后自己跟踪元素的数量,但很快就会变得一团糟,无法给出准确的结果并可能给出近似的结果。

如果你对LinkedTransferQueue没有任何硬依赖,那么你可以使用一些BlockingQueue的味道,其中许多使你能够以某种方式拥有一个“有界”的队列(有界队列就是你所需要的) - 例如,ArrayBlockingQueue是隐含有界,你可以像这个LinkedBlockingQueue创建一个有界的new LinkedBlockingQueue(100)。您可以查看其他队列的文档。

然后你可以使用队列的offer方法,如果队列已满,它将返回FALSE,所以如果你得到FALSE然后你可以按你想要的那样处理,所以你不需要做明确的大小检查,你可以简单地使用offer方法将元素放入队列中,它将返回一个布尔值,指示元素是否已成功放入队列中。


1
投票

你试过ArrayBlockingQueue吗?

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ArrayBlockingQueue.html

它具有大小限制和并发性。

此外,大小为O(1)。

public int size() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return count;
    } finally {
        lock.unlock();
    }
}

0
投票

你能不能通过BlockingQueue。这是我在互联网上找到的最佳链接 - BlockingQueueBlockingQueue是一个接口,它在包中 - java.util.concurrent,它有多个实现: -

  1. ArrayBlockingQueue
  2. DelayQueue
  3. LinkedBlockingQueue
  4. PriorityBlockingQueue
  5. SynchronousQueue
© www.soinside.com 2019 - 2024. All rights reserved.