Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java blocking queue containing only unique elements

Tags:

java

queue

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?

like image 743
ʞɔıu Avatar asked Mar 08 '11 19:03

ʞɔıu


2 Answers

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;
    }
}
like image 76
horec Avatar answered Sep 20 '22 06:09

horec


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.

like image 34
Spike Gronim Avatar answered Sep 18 '22 06:09

Spike Gronim