One of the most significant improvements offered by locks is the ReadWriteLock interface and the ReentrantReadWriteLock class, the unique one that implements it. This class has two locks, one for read operations and one for write operations. There can be more than one thread using read operations simultaneously, but only one thread can be using write operations. When a thread is doing a write operation, there can't be any thread doing read operations.
In this article, you will learn how to use a ReadWriteLock interface implementing a program that uses it to control the access to an object that stores the prices of two books
BookInfo class
Create a class named Reader and specify that it implements the Runnable interface. This class implements a reader of the values of the BookInfo class attributes.
Create a class named Writer and specify that it implements the Runnable interface. This class implements a modifier of the values of the BookInfo class attributes.
Main class
As we mentioned previously, the ReentrantReadWriteLock class has two locks, one for read operations and one for write operations.
The lock used in read operations is obtained with the readLock() method declared in the ReadWriteLock interface. This lock is an object that implements the Lock interface, so we can use the lock(), unlock(), and tryLock() methods.
The lock used in write operations is obtained with the writeLock() method declared in the ReadWriteLock interface. This lock is an object that implements the Lock interface, so we can use the lock(), unlock(), and tryLock() methods.
It is the responsibility of the programmer to ensure the correct use of these locks, using them with the same purposes for which they were designed.When you get the read lock of a Lock interface, you can't modify the value of the variable. Otherwise, you probably will have inconsistency data errors.
If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...
A classic problem in concurrent programming is the producer-consumer problem. We have a data buffer, one or more producers of data that save it in the buffer and one or more consumers of data that take it from the buffer.
As the buffer is a shared data structure, we have to control the access to it using a synchronization mechanism such as the synchronized keyword, but we have more limitations. A producer can't save data in the buffer if it's full and the consumer can't take data from the buffer if it's empty
For these types of situations, Java provides the wait(), notify(), and notifyAll() methods implemented in the Object class. A thread can call the wait() method inside a synchronized block of code. If it calls the wait() method outside a synchronized block of code, the JVM throws an IllegalMonitorStateException exception. When the thread calls the wait() method, the JVM puts the thread to sleep and releases the object that controls the synchronized block of code that it's executing and allows the other threads to execute other blocks of synchronized code protected by that object. To wake up the thread, you must call the notify() or notifyAll() method inside a block of code protected by the same object.
In this article, you will learn how to implement the producer-consumer problem using the synchronized keyword and the wait(), notify(), and notifyAll() methods
Storage class
It has two attributes: an int attribute called maxSize and a LinkedList<Date> attribute called list.
Implement the synchronized method set() to store an event in the storage. First, check if the storage is full or not. If it's full, it calls the wait() method until the storage has empty space. At the end of the method, we call the notifyAll() method to wake up all the threads that are sleeping in the wait() method.
Implement the synchronized method get() to get an event for the storage. First, check if the storage has events or not. If it has no events, it calls the wait() method until the storage has some events. At the end of the method, we call the notifyAll() method to wake up all the threads that are sleeping in the wait() method.
Producer and Consumer
Create a class named Producer and Consumer and specify that it implements the Runnable interface.
Main Class
Sample Output
How it works...
The key to this example is the set() and get() methods of the EventStorage class. First of all, the set() method checks if there is free space in the storage attribute. If it's full, it calls the wait() method to wait for free space. When the other thread calls the notifyAll() method, the thread wakes up and checks the condition again. The notifyAll() method doesn't guarantee that the thread will wake up. This process is repeated until there is free space in the storage and it can generate a new event and store it.
The behavior of the get() method is similar. First, it checks if there are events on the storage. If the EventStorage class is empty, it calls the wait() method to wait for events. Where the other thread calls the notifyAll() method, the thread wakes up and checks the condition again until there are some events in the storage.
If you run this example, you will see how producer and consumer are setting and getting the events, but the storage never has more than 10 events.
If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...
UncaughtExceptionHandler is interface for handlers invoked when a Thread abruptly terminates due to an uncaught exception. Basically, this is a mechanism to catch and treat the unchecked exception thrown in a thread object that what we are going to see in this article.
There are two kinds of exceptions in Java:
- Checked exceptions: These exceptions must be specified in the throws clause of a method or caught inside them. For example, IOException or classNotFoundException.
- Unchecked exceptions: These exceptions don't have to be specified or caught. For example, NumberFormatException.
When a checked exception is thrown inside the run() method of a Thread object, we have to catch and treat them, because the run() method doesn't accept a throws clause. When an unchecked exception is thrown inside the run() method of a Thread object, the default behaviour is to write the stack trace in the console and exit the program
Fortunately, Java provides us with a mechanism to catch and treat the unchecked exceptions thrown in a Thread object to avoid the program ending
First of all, we have to implement a class to treat the unchecked exceptions. This class must implement the UncaughtExceptionHandler interface and implement the uncaughtException() method declared in that interface. In our case, call this class ExceptionHandler and make the method to write information about Exception and Thread that threw it. Following is the code:
Now, implement a class that throws an unchecked exception
Now, implement the main class of the example
When an exception is thrown in a thread and is not caught (it has to be an unchecked exception), the JVM checks if the thread has an uncaught exception handler set by the corresponding method. If it has, the JVM invokes this method with the Thread object and Exception as arguments.
If the thread has not got an uncaught exception handler, the JVM prints the stack trace in the console and exits the program.
There is more....
The Thread class has another method related to the process of uncaught exceptions. It's the static method setDefaultUncaughtExceptionHandler() that establishes an exception handler for all the Thread objects in the application.
When an uncaught exception is thrown in Thread, the JVM looks for three possible handlers for this exception.
First, it looks for the uncaught exception handler of the Thread objects as we learned in this recipe. If this handler doesn't exist, then the JVM looks for the uncaught exception handler for ThreadGroup of the Thread objects as was explained in the Processing uncontrolled exceptions in a group of threads recipe. If this method doesn't exist, the JVM looks for the default uncaught exception handler as we learned in this recipe.
If none of the handlers exits, the JVM writes the stack trace of the exception in the console and exits the program.
If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...