It happens that in our system's architecture we have a situation of concurrent access to some collection. Whether it's a server that handles requests via sockets or a JMS listener, it usually stores incoming objects into a collection and other worker processes them. It can be illustrated as a well known producer-consumer problem.
An example implementation could look like that:
We have a class that serves as our producer.
In an endless loop we're sending random strings to a queue. Access to it is synchronized by acquiring its monitor. We're sleeping 1 ms so that the processor is not over-killed.
Let's take a look at a consumer:
It synchronizes queue in a similar way. What is more, before taking from the queue, it checks if it's not empty. It also sleeps 1 ms for the same reason as producer.
Class that glues them together:
We're using LinkedList as an implementation of our Queue. Producer and consumer are started in a separate threads.
There are at least 3 major drawbacks with this implementation.
First of all we're acquiring monitor of the queue, so we're completely blocking access to it not allowing for a concurrent access.
Secondly we need to check if the queue is not empty before taking from it.
Last but not least, consumer sleeps some specified time (sleeping when you're supposed to be working is not the best thing to do) and our performance decreases.
The remedy for above problems is BlockingQueue.
The new producer is similar to previous one, except that it operates on BlockingQueue and doesn't use any synchronization on it, because it's thread safe.
There are some changes in consumer:
Apart from not using synchronization, we don't need to check if the queue is not empty, as method take() is doing it for us. We also don't have to sleep anymore, as it is also handled by this method: as soon as an element is available it will be taken from the queue.
Class to run it:
It hasn't changed much, we're using LinkedBlockingQueue as an implementation.
There are other implementations of BlockingQueue that may be helpful for our needs (e.g. that introduces priority to elements or some delay that is needed before taking).