In Java, communication between threads can be controlled using wait, notify, and notifyAll. These three methods are all multithreaded, as their names suggest, but you might be surprised to learn that they are not Thread or Runnable methods, but three native methods of Object.

In addition, I have compiled the interview questions for 20 years, including Spring, concurrency, database, Redis, distributed, Dubbo, JVM, microservices and other aspects of the summary, if you need to get:Tencent document

To invoke wait and notify/notifyAll on an Object, ensure that the code is synchronized with the Object, that is, synchronized(obj){…… } obj wait and notify/notifyAll are called internally. Otherwise, an error is reported:

  java.lang.IllegalMonitorStateException:current thread not owner
Copy the code

In other words, the current Thread must acquire the lock of the Object when it calls the three methods. Therefore, the three methods are related to the Object lock, and therefore belong to the Object method, not the Thread, because not every Object is a Thread. So before we understand wait, notify, and notifyAll, we need to understand the following object locks.

Synchronized (obj){…… if multiple threads hold the same object }, and must acquire the lock of the object. Synchronized ensures that only one thread can acquire the lock of the object at a time, as shown in the following figure:

Let’s take a look at the three methods in action:

  • Wait: A thread automatically releases the lock it holds on an object and waits for notify
  • Notify: Wake up a thread that is waiting for the current object lock and let it get the lock
  • NotifyAll: Wakes up all threads that are locking objects before waiting

The main difference between notify and notifyAll is that notify awakens only one thread that is waiting for the current lock, while notifyAll awakens all threads. Note that notify is a local method, and the virtual machine controls which thread to wake up. NotifyAll not all threads can execute immediately after notifyAll, they are only out of wait, and they are then competing locks.

The following is a common producer, consumer example to illustrate. Message entity class:

package com.podongfeng;

/** * Title: Message. Class <br> * Description: Message entity <br> * Create DateTime: 2016年04月17日 1:27 PM <br> **@author podongfeng
 */
public class Message {}Copy the code

Producers:

package com.podongfeng;

import java.util.ArrayList;
import java.util.List;

/** * Title: Producer. Class <br> * Description: message Producer <br> * Create DateTime: April 17, 2016 1:28 PM <br> **@author podongfeng
 */
public class Producer extends Thread {

    List<Message> msgList = new ArrayList<>();

    @Override public void run(a) {
        try {
            while (true) {
                Thread.sleep(3000);
                Message msg = new Message();
                synchronized(msgList) {
                    msgList.add(msg);
                    msgList.notify(); / / here is only notify is not notifyAll, or remove (0) to Java. Lang. IndexOutOfBoundsException: Index: 0, Size: 0}}}catch(Exception e) { e.printStackTrace(); }}public Message waitMsg(a) {
        synchronized(msgList) {
            if(msgList.size() == 0) {
                try {
                    msgList.wait();
                } catch(InterruptedException e) { e.printStackTrace(); }}return msgList.remove(0); }}}Copy the code

Consumer:

package com.podongfeng;

/** * Title: Consumer. Class <br> * Description: message Consumer <br> * Create DateTime: 2016年04月17日 1:28 PM <br> **@author podongfeng
 */
public class Consumer extends Thread {

    private Producer producer;

    public Consumer(String name, Producer producer) {
        super(name);
        this.producer = producer;
    }

    @Override public void run(a) {
        while (true) {
            Message msg = producer.waitMsg();
            System.out.println("Consumer " + getName() + " get a msg"); }}public static void main(String[] args) {
        Producer p = new Producer();
        p.start();
        new Consumer("Consumer1", p).start();
        new Consumer("Consumer2", p).start();
        new Consumer("Consumer3", p).start(); }}Copy the code

The consumer thread calls waitMsg to retrieve a message entity, and if msgList is empty, the thread enters the wait state. The production thread produces the physical MSG entity every 3 seconds and puts it into the msgList list. When it’s done, call notify to wake up a consumer thread to consume it.

Wait, notify, and notifyAll are not methods of Thread or Runnable. They are native methods of Object. When these three methods are called, the current thread must acquire the lock on the object

The final routine: a small praise, good luck, attention, permanent youth, a small reward, salary increase…