Java 并发集合队列
也许这是一个愚蠢的问题,但我似乎找不到一个明显的答案Java 并发集合队列,java,collections,concurrency,queue,set,Java,Collections,Concurrency,Queue,Set,也许这是一个愚蠢的问题,但我似乎找不到一个明显的答案 我需要一个只包含唯一值的并发FIFO队列。尝试添加队列中已存在的值只会忽略该值。如果不是为了线程安全,这将是微不足道的。Java中是否有数据结构,或者Interweb上是否有代码窃听器可以显示这种行为?没有内置的集合可以做到这一点。有一些并发Set实现可以与并发队列一起使用 例如,只有在项目成功添加到集合中之后,才会将其添加到队列中,并且从队列中删除的每个项目都会从集合中删除。在这种情况下,从逻辑上讲,队列的内容实际上是集合中的任何内容,而队
我需要一个只包含唯一值的并发FIFO队列。尝试添加队列中已存在的值只会忽略该值。如果不是为了线程安全,这将是微不足道的。Java中是否有数据结构,或者Interweb上是否有代码窃听器可以显示这种行为?没有内置的集合可以做到这一点。有一些并发
Set
实现可以与并发队列一起使用
例如,只有在项目成功添加到集合中之后,才会将其添加到队列中,并且从队列中删除的每个项目都会从集合中删除。在这种情况下,从逻辑上讲,队列的内容实际上是集合中的任何内容,而队列只是用来跟踪顺序,并提供有效的take()
和poll()
操作,这些操作仅在BlockingQueue
上才能找到
用自己的类包装ConcurrentLinkedQueue,该类检查add的唯一性。您的代码必须是线程安全的。如果您想要比完全同步更好的并发性,我知道有一种方法可以做到这一点,使用ConcurrentHashMap作为备份映射。以下仅为示意图
public final class ConcurrentHashSet<E> extends ForwardingSet<E>
implements Set<E>, Queue<E> {
private enum Dummy { VALUE }
private final ConcurrentMap<E, Dummy> map;
ConcurrentHashSet(ConcurrentMap<E, Dummy> map) {
super(map.keySet());
this.map = Preconditions.checkNotNull(map);
}
@Override public boolean add(E element) {
return map.put(element, Dummy.VALUE) == null;
}
@Override public boolean addAll(Collection<? extends E> newElements) {
// just the standard implementation
boolean modified = false;
for (E element : newElements) {
modified |= add(element);
}
return modified;
}
@Override public boolean offer(E element) {
return add(element);
}
@Override public E remove() {
E polled = poll();
if (polled == null) {
throw new NoSuchElementException();
}
return polled;
}
@Override public E poll() {
for (E element : this) {
// Not convinced that removing via iterator is viable (check this?)
if (map.remove(element) != null) {
return element;
}
}
return null;
}
@Override public E element() {
return iterator().next();
}
@Override public E peek() {
Iterator<E> iterator = iterator();
return iterator.hasNext() ? iterator.next() : null;
}
}
公共最终类ConcurrentHashSet扩展了ForwardingSet
实现集合、队列{
私有枚举伪值{VALUE}
私有最终ConcurrentMap地图;
ConcurrentHashSet(ConcurrentMap映射){
super(map.keySet());
this.map=premissions.checkNotNull(map);
}
@重写公共布尔添加(E元素){
返回map.put(元素,Dummy.VALUE)==null;
}
@重写公文布尔加法(集合< P>),我将使用同步的Link KHASHSET,直到有足够的理由来考虑替代方案。更为并行的解决方案可以提供的主要好处是锁拆分。
最简单的并发方法是ConcurrentHashMap(作为一个集合)和ConcurrentLinkedQueue。操作的顺序将提供所需的约束。offer()将首先执行CHM#putIfAbsent(),如果成功插入CLQ。a poll()将从CLQ取走,然后从CHM中删除它。这意味着如果我们在队列中考虑一个条目,如果它在映射中,并且CLQ提供排序。那么可以通过增加MAP的并发级别来调整性能。可以作为一个合理的先决条件(但它可能会受到稍微陈旧的视图的影响)。您所说的具有设置语义的并发队列是什么意思?如果您指的是真正的并发结构(而不是线程安全结构),那么我认为您是在要求一个小马
例如,如果调用put(element)
并检测到某个已存在且立即被删除的内容,会发生什么情况?例如,如果offer(element)| | queue.contains(element)
返回false
,则在您的情况下这意味着什么
在一个并发的世界中,这类事情通常需要稍微不同的思考,因为除非你停止这个世界(锁定它),否则一切都不会是看起来的样子。否则你通常会看到过去的事情。那么,你实际上想做什么呢?也许是扩展。为了访问(包访问)lock,我必须把我的子类放在同一个包中。警告:我还没有测试过这个
package java.util.concurrent;
import java.util.Collection;
import java.util.concurrent.locks.ReentrantLock;
public class DeDupingBlockingQueue<E> extends ArrayBlockingQueue<E> {
public DeDupingBlockingQueue(int capacity) {
super(capacity);
}
public DeDupingBlockingQueue(int capacity, boolean fair) {
super(capacity, fair);
}
public DeDupingBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) {
super(capacity, fair, c);
}
@Override
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (contains(e)) return false;
return super.add(e);
} finally {
lock.unlock();
}
}
@Override
public boolean offer(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (contains(e)) return true;
return super.offer(e);
} finally {
lock.unlock();
}
}
@Override
public void put(E e) throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly(); //Should this be lock.lock() instead?
try {
if (contains(e)) return;
super.put(e); //if it blocks, it does so without holding the lock.
} finally {
lock.unlock();
}
}
@Override
public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (contains(e)) return true;
return super.offer(e, timeout, unit); //if it blocks, it does so without holding the lock.
} finally {
lock.unlock();
}
}
}
包java.util.concurrent;
导入java.util.Collection;
导入java.util.concurrent.locks.ReentrantLock;
公共类DuplicatingBlockingQueue扩展了ArrayBlockingQueue{
公共重复数据块队列(整数容量){
超级(容量);
}
公共重复数据块队列(整数容量,布尔公平){
超级(容量,公平);
}
public duplicatingblockingqueue(int-capacity、boolean-fair、Collection唯一对象队列的简单答案如下:
import java.util.concurrent.ConcurrentLinkedQueue;
public class FinalQueue {
class Bin {
private int a;
private int b;
public Bin(int a, int b) {
this.a = a;
this.b = b;
}
@Override
public int hashCode() {
return a * b;
}
public String toString() {
return a + ":" + b;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Bin other = (Bin) obj;
if ((a != other.a) || (b != other.b))
return false;
return true;
}
}
private ConcurrentLinkedQueue<Bin> queue;
public FinalQueue() {
queue = new ConcurrentLinkedQueue<Bin>();
}
public synchronized void enqueue(Bin ipAddress) {
if (!queue.contains(ipAddress))
queue.add(ipAddress);
}
public Bin dequeue() {
return queue.poll();
}
public String toString() {
return "" + queue;
}
/**
* @param args
*/
public static void main(String[] args) {
FinalQueue queue = new FinalQueue();
Bin a = queue.new Bin(2,6);
queue.enqueue(a);
queue.enqueue(queue.new Bin(13, 3));
queue.enqueue(queue.new Bin(13, 3));
queue.enqueue(queue.new Bin(14, 3));
queue.enqueue(queue.new Bin(13, 9));
queue.enqueue(queue.new Bin(18, 3));
queue.enqueue(queue.new Bin(14, 7));
Bin x= queue.dequeue();
System.out.println(x.a);
System.out.println(queue.toString());
System.out.println("Dequeue..." + queue.dequeue());
System.out.println("Dequeue..." + queue.dequeue());
System.out.println(queue.toString());
}
}
import java.util.concurrent.ConcurrentLinkedQueue;
公共类最终队列{
分类箱{
私人INTA;
私人INTB;
公共垃圾箱(内部a、内部b){
这个a=a;
这个.b=b;
}
@凌驾
公共int hashCode(){
返回a*b;
}
公共字符串toString(){
返回a+“:”+b;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(getClass()!=obj.getClass())
返回false;
Bin其他=(Bin)obj;
如果((a!=其他.a)|(b!=其他.b))
返回false;
返回true;
}
}
私有ConcurrentLinkedQueue队列;
公共最终队列(){
队列=新的ConcurrentLinkedQueue();
}
公共已同步的无效队列(Bin IP地址){
如果(!queue.contains(ipAddress))
queue.add(ipAddress);
}
公共垃圾箱出列(){
返回queue.poll();
}
公共字符串toString(){
返回“”+队列;
}
/**
*@param args
*/
公共静态void main(字符串[]args){
FinalQueue=新的FinalQueue();
Bin a=队列。新Bin(2,6);
排队。排队(a);
queue.enqueue(queue.newbin(13,3));
queue.enqueue(queue.newbin(13,3));
queue.enqueue(queue.newbin(14,3));
queue.enqueue(queue.newbin(13,9));
queue.enqueue(queue.newbin(18,3));
queue.enqueue(queue.newbin(14,7));
Bin x=queue.dequeue();
系统输出打印LN(x.a);
System.out.println(queue.toString());
System.out.println(“Dequeue…”+queue.Dequeue());
System.out.println(“Dequeue…”+queue.Dequeue());
System.out.println(queue.toString());