BoundedHashSet use a semaphore to turn a set (no bound) into a blocking bounded set. The semaphore is initialized to the desired maximum size of the collection. The add operation acquires a permit before adding an item. The try-finally block guarantees that if the add operation does not actually add anything, it releases the permit immediately. A successful remove also releases a permit, enabling more elements to be added.
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Semaphore;
//TODO, use Chapter 12 materials to test this class
class BoundedHashSet <T> {
private final Set<T> set;
private final Semaphore sem;
public BoundedHashSet(int bound) {
this.set = Collections.synchronizedSet(new HashSet<T>());
sem = new Semaphore(bound);
}
public boolean add(T o) throws InterruptedException {
sem.acquire();
boolean wasAdded = false;
try {
wasAdded = set.add(o);
return wasAdded;
} finally {
if (!wasAdded)
sem.release();
}
}
public boolean remove(Object o) {
boolean wasRemoved = set.remove(o);
if (wasRemoved)
sem.release();
return wasRemoved;
}
}