仅包含唯一元素的 Java 阻塞队列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5237283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java blocking queue containing only unique elements
提问by ???u
sort of like a "blocking set". How can I implement a blocking queue where adding a member that is already in the set is ignored?
有点像“阻塞集”。如何实现一个阻塞队列,其中添加一个已经在集合中的成员被忽略?
回答by horec
I wrote this class to solve a similar problem:
我编写了这个类来解决类似的问题:
/**
* Linked blocking queue with {@link #add(Object)} method, which adds only element, that is not already in the queue.
*/
public class SetBlockingQueue<T> extends LinkedBlockingQueue<T> {
private Set<T> set = Collections.newSetFromMap(new ConcurrentHashMap<>());
/**
* Add only element, that is not already enqueued.
* The method is synchronized, so that the duplicate elements can't get in during race condition.
* @param t object to put in
* @return true, if the queue was changed, false otherwise
*/
@Override
public synchronized boolean add(T t) {
if (set.contains(t)) {
return false;
} else {
set.add(t);
return super.add(t);
}
}
/**
* Takes the element from the queue.
* Note that no synchronization with {@link #add(Object)} is here, as we don't care about the element staying in the set longer needed.
* @return taken element
* @throws InterruptedException
*/
@Override
public T take() throws InterruptedException {
T t = super.take();
set.remove(t);
return t;
}
}
回答by Spike Gronim
You can create a new class that composes a BlockingQueue, a Set, and a lock. When you put() you test against the set while holding a lock that prevents get() from running. When you get() you remove the item from the set so that it can be put() again in the future.
您可以创建一个由 BlockingQueue、Set 和锁组成的新类。当您 put() 时,您在持有阻止 get() 运行的锁的同时对集合进行测试。当您 get() 时,您从集合中删除该项目,以便将来可以再次 put() 。
回答by forhas
A blocking queue implementation backed by a linked hash set for predictable iteration order and constant time addition, removal and contains operations:
由链接散列集支持的阻塞队列实现,用于可预测的迭代顺序和恒定时间添加、删除和包含操作:
你去吧。
回答by Howard
You can override add and put methods of any implementation of BlockingQueue<T>
to check first if the element is already within the queue, e.g.
您可以覆盖任何实现的 add 和 put 方法BlockingQueue<T>
以首先检查元素是否已经在队列中,例如
@Override
public boolean add(T elem) {
if (contains(elem))
return true;
return super.add(elem);
}
回答by brayne
class BlockingSet extends ArrayBlockingQueue<E> {
/*Retain all other methods except put*/
public void put(E o) throws InterruptedException {
if (!this.contains(o)){
super.put(o);
}
}
}