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