1

I want a thread-safe container that blocks the caller until an item becomes available. Items will be added at a rate of 1000s per second to this container but will not be drained the same rate. Therefore, I want the container to disallow duplicates. I wrote a very simple wrapper around LinkedBlockingQueue but soon realized that I've recreated the classic producer-consumer deadlock. This is what I had written:

public class ActivityListener {
    private final BlockingQueue<ID> activeItems = new LinkedBlockingQueue<>();

    public synchronized ID take() throws InterruptedException {
        return activeItems.take();
    }

    public synchronized void registerActivity(final ID item) {
        if (!activeItems.contains(item)) {
            activeItems.add(item);
        }
    }

    public synchronized boolean isItemActive(final ID item) {
        return activeItems.contains(item);
    }
}

I could not find an established solution to my problem and would appreciate any help.

user1071840
  • 3,522
  • 9
  • 48
  • 74

1 Answers1

-1

Override the add() and put() methods of any implementation of BlockingQueue to check first if the element is already within the queue.

Something like -

@Override
public boolean add(T obj) {
    if (contains(obj))
        return true;
    return super.add(obj);
}
Raman Shrivastava
  • 2,923
  • 15
  • 26
  • 1
    that isn't thread-safe and unfortunately probably cannot be made so (at least in the general case). – jtahlborn Jul 10 '15 at 22:26
  • Also, returning true from an add method on a set-like interface when an object is not added to the set is very non-idiomatic. – wickstopher Jul 11 '15 at 03:13