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 - BlockingQueue。 BlockingQueue
是一个接口,它在包中 - java.util.concurrent 并且它有多个实现:-
ArrayBlockingQueue
DelayQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronousQueue
BlockingQueue
是
BlockingQueue implementations are thread-safe
[...]
A BlockingQueue may be capacity bounded.
并且 ArrayBlockingQueue
是
以下是您如何使用它编写示例:
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 你一个布尔值,指示元素是否已成功放入队列中。
为了实现 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 - BlockingQueue。 BlockingQueue
是一个接口,它在包中 - java.util.concurrent 并且它有多个实现:-
ArrayBlockingQueue
DelayQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronousQueue
BlockingQueue
是
BlockingQueue implementations are thread-safe
[...]
A BlockingQueue may be capacity bounded.
并且 ArrayBlockingQueue
是
以下是您如何使用它编写示例:
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 你一个布尔值,指示元素是否已成功放入队列中。