Concurrent Collections & Maps
BlockingQueue
- Failing with an IllegalArgumentException (add(), addFirst(), peek(), remove())
- Failing and returning false (offer(), offerFirst(), poll(), pollFirst())
- Blocking until the queue can accept the element (put(), putFirst(), take(), takeFirst())
private static BlockingQueue<String> queue = new ArrayBlockingQueue<>(50); // bounded in size
//private static BlockingQueue<String> queue = new LinkedBlockingQueue<>(); //unbounded size
queue.take();
queue.put(x);
Simple implementation of Blocking Queue:
public class BlockingQueue {
private List queue = new LinkedList();
private int limit = 10;
public BlockingQueue(int limit){
this.limit = limit;
}
public synchronized void enqueue(Object item) throws InterruptedException {
while(this.queue.size() == this.limit) {
wait();
}
//notifyAll() is only called from enqueue() and dequeue() if the queue size is equal to the size bounds (0 or limit)
if(this.queue.size() == 0) {
notifyAll();
}
this.queue.add(item);
}
public synchronized Object dequeue() throws InterruptedException{
while(this.queue.size() == 0){
wait();
}
if(this.queue.size() == this.limit){
notifyAll();
}
return this.queue.remove(0);
}
}
ConcurrentMap
atomic operations:
- putIfAbsent(key, value)
- computeIfAbsent(key, a -> new HashSet<>())
- remove(key, value)
- replace(key, value)
- replace(key, existingValue, newValue)
ConcurrentHashMap supports very high concurrency, for reduce, search operations.
ConcurrentHashMap<Actor, Set<Movie>> map = new ConcurrentHashMap<>();
MovieReader reader = new MovieReader();
reader.addActorsToMap(map);
//map.computeIfAbsent(actor, a -> new HashSet<>()).add(movie);
System.out.println("# Actors = " + map.size());
int maxMoviesForOneActor = map.reduce(20, (actor, movies)->movies.size(), Integer::max);
Actor mostSeenActor = map.search(10, (actor, movies)-> movies.size()==maxMoviesForOneActor? actor:null);
System.out.println("Most seen actor = " + mostSeenActor);
int numberOfMoviesReference = map.reduce(10, (actor, movies)->movies.size(), Integer::sum);
System.out.println("Average movies per actor = " + numberOfMoviesReference/map.size());