How do Java threads communicate with each other? Why do threads need to communicate with each other? Why do you have wait, notify, and notifyAll methods in the java.lang.Object class? How to solve the producer-consumer problem with inter-thread communication?
In the last Java multi-threading post, we looked at "Understanding Java locks, multi-threading, and synchronized keyword", which is a very important subject to understand intrinsic and explicit locks, what to watch out for in explicit locks, and when to use explicit locks, etc. In this post let's look at inter thread communication.
Q. Why do threads need to communicate with each other?
A. Inter thread communication is very similar inter process communication where 2 or more processes communicate with other, the only difference being that inter thread communication happens within the same process (i.e. within the same memory model). Inter thread communication means two or more threads exchange data with each other.
Example 1: A ChatServer with two or more threads presenting user sessions, and these threads (i.e. chat users) need to communicate with each other.
Example 2: A Producer-Consumer (also known as the bounded-buffer problem) scenario, where the producer and the consumer, who share a common, fixed-size buffer used as a queue. The producer's job is to generate a piece of data, put it into the buffer and start again. At the same time, the consumer is consuming the data (i.e., removing it from the buffer) one piece at a time. The problem is to make sure that the producer won't try to add data into the buffer if it's full and that the consumer won't try to remove data from an empty buffer.
Example 3: A MessageBroker class that receives messages from a Java Servlet (i.e inherently multi-threaded) via a BlockingQueue and a separate asynchronous Servlet that is the message sender to the MessageBroker. The message senders and receivers need to communicate with each other. Similar, example can be given for email sender and receiver via a blocking queue, etc.
Q. How do Java threads communicate with each other?
A. In inter process communication, two or more processes communicate with each other using
- Pipes (e.g. Unix processes ps -ef | grep Java).
- Sockets(Java processes using java.io.Reader and Java.io.Writer, RMI, etc).
In Java, every object extends the java.lang.Object class, which has 3 final methods for inter-thread communication. Those methods are wait( ), notify ( ), and notifyAll( ), and these methods are used to provide an efficient way for threads to communicate with each other.
Here is a very simple example,
Q. What must you know about using wait () and notifyAll( ) properly?
A. Here are 5 things you must know to use wait( ) / notify( ) for inter thread communication
- Use the same object for calling wait() and notify() method as every object in Java has its own lock. so calling wait() on objA and notify() on obj B will not make any sense, and will not give you inter-thread communication.
- In order to wait or notify, you need to "own" the object's lock first. So, the method or block must be synchronized.
- You need to wait( ) or notify() on the same object you have acquired the lock for.
- use notifyAll() instead of notify() if you expect more than one thread is waiting for lock.
- Always call wait() method in a loop because if multiple threads are waiting for lock and one of them got lock and reset the condition and the other thread needs to check the condition after they got woken up to see whether they need to wait again or can start processing.
Now, here are detailed examples of inter-thread communication in Java.
Q. How will you print odd and even numbers with 2 threads communicating with each other?
A. Here are fully working code using 3 different approaches wait/notify, piped reader/writer, and a blocking queue.
Example 1 with working code: Printing odd and even numbers with inter-thread communication via wait() and notifyAll() methods
Example 2 with working code and diagrams: Printing odd and even numbers with inter-thread communication via piped reader and writer
Example 3 with working code and diagram: Printing odd and even numbers with inter-thread communication via a blocking queue.
- In Java, an object itself shared between threads, and each object intrinsically has a lock, which allows thread to share a object, and communicate with each other.
- If wait( ) and notify( ) were on the Thread instead then each thread would have to know the status of every other thread.
- Since wait/notify are in the java.lang.Object class, the threads don't need to have specific knowledge of each other and they can run asynchronously.