Java Concurrency Utilities provides a number of powerful and high-performance threading utiities. At the high level they can be grouped into four categories and this article will cover one of the categories.
- Thread Pools and Task Scheduling
- Concurrent Collections
- Locks and Synchronizers
- Atomic Variables
We all know that Java supports synchronization since day one through the synchronized keyword, but the limitation is that this mechanism works at the block level and is limited to a single thread at a time. A number of new mechanisms were introduced. Among them are semaphore, barrier, latch and exchanger.
Semaphore are used to control or limit the number of activities that can access a certain resource or perform a given action at the same time. An easier way to understanding and remembering what a Semaphore is by associating Semaphore with permits. A semaphore maintains a set of permits and a thread must acquire a permit from the semaphore before it can obtain a resource or perform a certain activity. The permit is returned to the semaphore when thread is done accessing a resource or perform a certain activity. If all the permits were already given out, then the next thread that asks fro a permit will be blocked.
Latch is used to allow one or more threads to wait for a set of threads to complete an action. Once a latch is set, it never changes. Latch is commonly used to coordinate certain threads and the common use case for latch is start several threads and have them wait until a signal is received from a coordinating thread. Another example in a multiplayer games is you don’t want the game to start until all the players have joined.
CyclicBarrier is used to create a barrier and there are two different kinds of barrier. The first kind is a barrier with a number of threads and the other is a number of threads and a barrier action. The barrier action is a Runnable task that runs when all the threads have joined together. Basically a barrier is used stop a set of threads from running until they all reach a specified point. Comparing to a latch, which is used to let threads run wild, a barrier is used stop a set of thread.
Out of the four kinds of synchronizers, exchanger is a unique one. It is used to allow two threads to exchange data in thread-safe manner. Imagine the producer and consumer problem, an exchanger can be used to allow producer and consumer to exhange the buffer that contains tasks to do in one shot, instead of consumer picks one task out of the task queue at a time.
Next article will cover Atomic Variables.