The java.util.concurrent package contains several classes that help manage a set of collaborating threads—see Table below. These mechanisms have “canned functionality” for common rendezvous patterns between threads. If you have a set of collaborating threads that follows one of these behavior patterns, you should simply reuse the appropriate library class instead of trying to come up with a handcrafted collection of locks and conditions.
Conceptually, a semaphore manages a number of permits. To proceed past the semaphore, a thread requests a permit by calling acquire. Only a fixed number of permits are available, limiting the number of threads that are allowed to pass. Other threads may issue permits by calling release. There are no actual permit objects. The semaphore simply keeps a count. Moreover, a permit doesn’t have to be released by the thread that acquires it. In fact, any thread can issue any number of permits. If it issues more than themaximum available, the semaphore is simply set to the maximum count. This generalitymakes semaphores both very flexible and potentially confusing.
Semaphores were invented by Edsger Dijkstra in 1968, for use as a synchronization primitive. Dijkstra showed that semaphores can be efficiently implemented and that they are powerful enough to solve many common thread synchronization problems. In just about any operating systems textbook, you will find implementations of bounded queues using semaphores. Of course, application programmers shouldn’t reinvent bounded queues. We suggest that you only use semaphores when their behavior maps well onto your synchronization problem, without your going through mental contortions.
One simple example is a semaphore with a permit count of 1. Such a semaphore can be used as a gate for one thread that is opened and closed by another thread. In the section “Example: Pausing and Resuming an Animation”, you will see an example in which a worker thread produces an animation. Occasionally, the worker thread waits for the user to press a button. The worker thread tries to acquire a permit, and it has to wait until the button click causes a permit to be issued.
A CountDownLatch lets a set of threads wait until a count has reached zero. The countdown latch is one-time only. Once the count has reached 0, you cannot increment it again. A useful special case is a latch with a count of 1. This implements a one-time gate.
Threads are held at the gate until another thread sets the count to 0. Imagine, for example, a set of threads that need some initial data to do their work. The worker threads are started and wait at the gate. Another thread prepares the data. When it is ready, it calls countDown, and all worker threads proceed.
You can then use a second latch to check when all worker threads are done. Initialize the latch with the number of threads. Each worker thread counts down that latch just before it terminates. Another thread that harvests the work results waits on the latch, and it proceeds as soon as all workers have terminated.
The CyclicBarrier class implements a rendezvous called a barrier. Consider a number of threads that are working on parts of a computation. When all parts are ready, the results need to be combined. When a thread is done with its part, we let it run against the barrier.
Once all threads have reached the barrier, the barrier gives way and the threads can proceed. Here are the details. First, construct a barrier, giving the number of participating threads:
The await method takes an optional timeout parameter:
If any of the threads waiting for the barrier leaves the barrier, then the barrier breaks. (A thread can leave because it called await with a timeout or because it was interrupted.) In that case, the await method for all other threads throws a BrokenBarrierException. Threads that are already waiting have their await call terminated immediately.
You can supply an optional barrier action that is executed when all threads have reached the barrier:
The barrier is called cyclic because it can be reused after all waiting threads have been released. In this regard, it differs from a CountDownLatch, which can only be used once.
An Exchanger is used when two threads are working on two instances of the same data buffer. Typically, one thread fills the buffer, and the other consumes its contents. When both are done, they exchange their buffers.
A synchronous queue is a mechanism that pairs up producer and consumer threads. When a thread calls put on a SynchronousQueue, it blocks until another thread calls take, and vice versa. Unlike the case with an Exchanger, data are only transferred in one direction, from the producer to the consumer.
Even though the SynchronousQueue class implements the BlockingQueue interface, it is not conceptually a queue. It does not contain any elements—its size method always returns 0.
Consider a program that does some work, updates the screen display, then waits for the user to look at the result and press a button to continue, and then does the next unit of work. A semaphore with a permit count of 1 can be used to synchronize the worker thread and the event dispatch thread. The worker thread calls acquire whenever it is ready to pause.
The GUI thread calls release whenever the user clicks the Continue button. What happens if the user clicks the button multiple times while the worker thread is ready? Because only one permit is available, the permit count stays at 1.
The program in Listing below puts this idea to work. The program animates a sorting algorithm. A worker thread sorts an array, stopping periodically and waiting for the user to give permission to proceed. The user can admire a painting of the current state of the algorithm and press the Continue button to allow the worker thread to go to the next step.
We didn’t want to bore you with the code for a sorting algorithm, so we simply call Arrays.sort, which implements the merge sort algorithm. To pause the algorithm, we supply a Comparator object that waits for the semaphore. Thus, the animation is paused wheneverthe algorithm compares two elements. We paint the current values of the array andhighlight the elements that are being compared (see Figure below).
NOTE: The animation shows the merging of smaller sorted ranges into larger ones, but it is not entirely accurate. The mergesort algorithm uses a second array for holding temporary values that we do not get to see. The point of this example is not to delve into sorting algorithms, but to show how to use a semaphore for pausing a worker thread.
Animating a sort algorithm
Core Java Related Interview Questions
|J2EE Interview Questions||Core Java Interview Questions|
|JDBC Interview Questions||JSP Interview Questions|
|Android Interview Questions||JavaServer Faces (JSF) Interview Questions|
|Java collections framework Interview Questions||Java 8 Interview Questions|
|Java Collections Interview Questions||Java Exception Handling Interview Questions|
|Java Concurrency Interview Questions||Java Serialization Interview Questions|
|Java Programmer Interview Questions||Java Inheritance Interview Questions|
|Java IO Interview Questions||Object Oriented Programming in PHP Interview Questions|
Core Java Tutorial
An Introduction To Java
The Java Programming Environment
Fundamental Programming Structures In Java
Objects And Classes
Interfaces And Inner Classes
User Interface Components With Swing
Deploying Applications And Applets
Exceptions, Logging, Assertions, And Debugging
All rights reserved © 2020 Wisdom IT Services India Pvt. Ltd
Wisdomjobs.com is one of the best job search sites in India.