Where produce-consumer pattern is present it is often the case that one is faster that the other:
a parsing producer reads records faster than a processing consumer;
a disk reading producer is faster than network sending consumer.
Producer and consumer often communicate by queues: the producer will put items on a queue while the consumer will pop items off a queue. What happens when the queue becomes full, or empty?
One approach of the producer is to try to put an item on a queue and if it’s full yield the thread and repeat. Similarly the consumer can try to pop an item off a queue and if it’s empty, ditto. This approach of try-fail-yield can unnecessarily burn CPU cycles in tight loops that constantly try to put or pop items off a queue.
Another approach is to temporarily grow the queue, but that doesn’t scale well. When do we stop growing? And once we stop we have to fall back onto the try-fail-yield method.
What if we could implement a blocking queue:
a queue who’s put operation blocks when the queue if full, and unblocks only when another thread pops an item off the queue
Similarly a queue who’s pop operation blocks when the queue is empty, and unblocks only when another thread puts an item on the queue.