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?
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;
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With