The wait(), notify(), and notifyAll() methods are the three methods of Object.
Wait () causes the current thread to wait until:
- Other thread calls
notify()
Methods ornotifyAll()
methods - Another thread interrupts the current thread
- The specified wait time is up
The way it’s used is in a loop
synchronized (obj) {
// The condition is not met
while (condition does not hold) {
obj.wait();
}
// Execute the code that meets the criteria
}
Copy the code
Calling wait() releases the lock on the current thread, leaving the CPU in the wait state. Notify () and notifyAll() both wake up the currently waiting thread. NotifyAll () wakes up all waiting threads. NotifyAll () wakes up all waiting threads. The thread will not execute the task immediately after being woken up. It is determined by the system which thread will execute the task. Wait (), notify(), and notifyAll() need to be included in the Syncronized code block or method.
Implement a consumer and producer pattern using wait(), notify(), and notifyAll().
Consumers and producers have a common container, from which consumers take data for consumption, and producers put data into the container after production. When the container is empty, consumers block, while producers produce data; When the container is full, the producer stops producing and notifies the consumer to consume.
The container
public class Container {
private static final int MAX_SIZE = 5;
private final LinkedList<Object> list = new LinkedList<>();
/ / production
public void product(a) {
synchronized (list) {
while (list.size() >= MAX_SIZE) { // The producer enters the wait state when the number of data in the container reaches the maximum
try {
System.out.println("The container is full. Yes." + list.size() + "A piece of data --" + Thread.currentThread().getName());
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.addFirst(new Object());
System.out.println("+++++ producer produces a piece of data that has" + list.size() + "A piece of data --"+ Thread.currentThread().getName()); list.notifyAll(); }}public void consume(a) {
synchronized (list) {
while (list.size() <= 0) { // If the container is empty, the consumer enters the wait state
try {
System.out.println("The container has no data --" + Thread.currentThread().getName());
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.removeLast();
System.out.println("----- consumer consumes a piece of data, there is" + list.size() + "A piece of data --"+ Thread.currentThread().getName()); list.notifyAll(); }}}Copy the code
producers
public class Producer implements Runnable{
private final Container mContainer;
public Producer(Container container) {
mContainer = container;
}
@Override
public void run(a) { mContainer.product(); }}Copy the code
consumers
public class Consumer implements Runnable {
private final Container mContainer;
public Consumer(Container container) {
mContainer = container;
}
@Override
public void run(a) { mContainer.consume(); }}Copy the code
public static void main(String[] args) {
Container container = new Container();
for (int i = 0; i < 8; i++) {
Producer producer = new Producer(container);
Thread thread = new Thread(producer);
thread.setName("Producer thread" + i);
thread.start();
}
for (int i = 0; i < 8; i++) {
Consumer consumer = new Consumer(container);
Thread thread = new Thread(consumer);
thread.setName("Consumer thread"+ i); thread.start(); }}Copy the code
Synchronized in the Container class holds a List lock, so wait(), notify(), and notifyAll() must all call list. Synchrozied can also hold this, which indicates that the current Container lock is synchronized, or synchronized, which means that the wait(), notify(), and notifyAll() methods must call the Container methods. Either this.wait() or wait().
There will be a follow-up article devoted to synchronized.