java 7/8 中具有大小限制的链接传输队列的任何替代方案?

Any alternatives for linkedtransfer queue with size restrictions in java 7/8?

为了实现 producer/consumer 模式,我使用了 LinkedTransferQueue

检查下面的代码

while (true) {

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

}

根据文档,它指出大小是 O(n) 操作:(。因此,要添加一个元素,它应该遍历整个集合。

是否还有其他有大小限制的并发收集队列? 在 java standard collections, apache concurrent collections 中找不到任何内容?

你试过了吗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();
    }
}

能否请您通过BlockingQueue。 这是我在互联网上找到的最好的 link - BlockingQueueBlockingQueue 是一个接口,它在包中 - java.util.concurrent 并且它有多个实现:-

  1. ArrayBlockingQueue
  2. DelayQueue
  3. LinkedBlockingQueue
  4. PriorityBlockingQueue
  5. SynchronousQueue

BlockingQueue

BlockingQueue implementations are thread-safe

[...]

A BlockingQueue may be capacity bounded.

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

或者一个简单的producer/consumer例子

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

@OP:你已经接受了答案,它也是正确的,但你仍然提高了赏金,所以我假设你更多地在寻找这个概念,所以我会阐明那部分。

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

  • 数据结构应该能够告诉您队列已满。
  • size 运算应该return 得到常数时间。

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

如果您对 LinkedTransferQueue 的目的有很强的依赖性,即您想根据某个元素在某个生产者队列中的时间长度来出队,那么我认为除了你可以做一些肮脏的事情,比如扩展 LinkedTransferQueue 然后自己跟踪元素的数量,但很快它就会变得一团糟,不能给你准确的结果,可能会给出近似的结果。

如果您对 LinkedTransferQueue 没有任何硬依赖,那么您可以使用 BlockingQueue 的某种风格,其中许多可以让您拥有 "bounded" 队列(有界队列是您所需要的)以某种方式或其他方式 - 例如,ArrayBlockingQueue 是隐式有界的,您可以像这样 new LinkedBlockingQueue(100) 创建一个有界的 LinkedBlockingQueue。您可以查看其他队列的文档。

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