Detailed analysis of wait of notify of notifyAll of for Java multithreading

  • 2020-04-01 02:01:33
  • OfStack

The wait (), notify () and notifyAll () Do not belong to Thread class , but belongs to Base class Object , that is, every object has one The wait (), notify () and notifyAll () function Because every object has a lock, the lock is the basis of every object, of course, the way to operate the lock is also the most basic.

Wait causes the current thread to wait until another thread invokes the object's Notify () Method or NotifyAll () Method, or is interrupted by another thread. A wait can only be called by a thread that holds a pair lock.

The notify wakes up a single thread waiting on this object's monitor. If all threads are waiting on this object, one of them (random) is chosen to wake up. The awakened thread cannot continue to execute until the current thread abandons the lock on the object. Like the Wait method, notify can only be called by a thread that holds a lock, and so can notifyall, except that notifyall calls all the threads that are waiting on the object lock.
"Can only be called by a thread holding a pair of locks" means that the wait and notify methods must be executed in a synchronized block, i.e., synchronized(obj). Complement each other.
Take a classic example (producers and consumers):
The first is the consumer thread class:

import java.util.List;
public class Consume implements Runnable {
 private List container = null;
 private int count;
 public Consume(List lst) {
  this.container = lst;
 }
 public void run() {
  while (true) {
   synchronized (container) {
    if (container.size() == 0) {
     try {
      container.wait();//The container is empty, give up the lock, and wait for production
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    container.remove(0);
    container.notify();
    System.out.println(" I ate " + (++count) + " a ");
   }
  }
 }
}

Next is the producer thread class:

import java.util.List;
public class Product implements Runnable {
 private List container = null;
 private int count;
 public Product(List lst) {
  this.container = lst;
 }
 public void run() {
  while (true) {
   synchronized (container) {
    if (container.size() > MultiThread.MAX) {
     //If the container exceeds its maximum value, don't produce and wait for consumption
     try {
      container.wait();
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
    }
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    container.add(new Object());
    container.notify();
    System.out.println(" I produced " + (++count) + " a ");
   }
  }
 }
}

Finally, the test class:

import java.util.ArrayList;
import java.util.List;
public class MultiThread {
 private List container = new ArrayList();
 public final static int MAX = 5;
 public static void main(String args[]) {
  MultiThread m = new MultiThread();
  new Thread(new Consume(m.getContainer())).start();
  new Thread(new Product(m.getContainer())).start();
 }
 public List getContainer() {
  return container;
 }
 public void setContainer(List container) {
  this.container = container;
 }
}

The results are as follows:

 I produced 1 a 
 I ate 1 a 
 I produced 2 a 
 I produced 3 a 
 I produced 4 a 
 I produced 5 a 
 I produced 6 a 
 I produced 7 a 
 I ate 2 a 
 I produced 8 a 
 I ate 3 a 
 I produced 9 a 
 I ate 4 a 
 I ate 5 a 
 I ate 6 a 
 I ate 7 a 
 I ate 8 a 
 I produced 10 a 
 I produced 11 a 
 I ate 9 a 
 I produced 12 a 
 I ate 10 a 
......


Related articles: