В java связью между потоками можно управлять с помощью wait, notify, notifyAll. Как видно из названий, эти три метода относятся к многопоточности, но что может вас удивить, так это то, что эти три метода являются не методами класса Thread или интерфейса Runnable, а тремя локальными методами класса Object. .
Кроме того, я собрал сборник вопросов для интервью за 20 лет, включая сводку по spring, concurrency, database, Redis, Distributed, dubbo, JVM, микросервисам и т. д. При необходимости вы можете получить его сами:Документация Тенсент
На самом деле понять это несложно.При вызове wait и notify/notifyAll Объекта необходимо убедиться, что вызывающий код синхронизирован с Объектом, то есть он должен быть эквивалентен synchronized(obj){ .... ..} может вызывать методы wait и notify/notifyAll объекта obj, иначе будет сообщено об ошибке:
java.lang.IllegalMonitorStateException:current thread not owner
Это,При вызове этих трех методов текущий поток должен получить блокировку этого объекта., то эти три метода связаны с блокировками объектов, поэтому они являются методами Object, а не Thread, поскольку не каждый объект является Thread. Итак, прежде чем мы поймем ожидание, уведомление, уведомлениеВсе, мы должны сначала понять следующие блокировки объектов.
Когда несколько потоков содержат один и тот же объект, если они хотят войти внутрь синхронизированного (объекта) {...}, они должны получить блокировку объекта. Синхронизированный механизм гарантирует, что не более чем 1 поток может получить объект. замок объекта, как показано ниже:
Давайте посмотрим на роль этих трех методов:
- ожидание: поток автоматически освобождает блокировку объекта, которую он удерживал, и ожидает уведомления.
- уведомить: разбудить поток, ожидающий блокировки текущего объекта, и позволить ему получить блокировку объекта
- Notibleall: просыпайтесь на все темы, которые ждут замок объекта до
Основное различие между notify и notifyAll заключается в том, что notify пробуждает только поток, ожидающий блокировки текущего объекта, а notifyAll пробуждает все. Стоит отметить, что: notify — локальный метод, и какой поток будить, контролирует виртуальная машина; не все потоки могут выполняться сразу после notifyAll, они просто выпрыгивают из состояния ожидания, а потом будут конкурировать за объектные замки.
Ниже приведен пример общего производителя и потребителя. Класс объекта сообщения:
package com.podongfeng;
/**
* Title: Message.class<br>
* Description: 消息实体<br>
* Create DateTime: 2016年04月17日 下午1:27 <br>
*
* @author podongfeng
*/
public class Message {
}
Режиссер:
package com.podongfeng;
import java.util.ArrayList;
import java.util.List;
/**
* Title: Producer.class<br>
* Description: 消息生产者<br>
* Create DateTime: 2016年04月17日 下午1:28 <br>
*
* @author podongfeng
*/
public class Producer extends Thread {
List<Message> msgList = new ArrayList<>();
@Override public void run() {
try {
while (true) {
Thread.sleep(3000);
Message msg = new Message();
synchronized(msgList) {
msgList.add(msg);
msgList.notify(); //这里只能是notify而不能是notifyAll,否则remove(0)会报java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Message waitMsg() {
synchronized(msgList) {
if(msgList.size() == 0) {
try {
msgList.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
return msgList.remove(0);
}
}
}
потребитель:
package com.podongfeng;
/**
* Title: Consumer.class<br>
* Description: 消息消费者<br>
* Create DateTime: 2016年04月17日 下午1:28 <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() {
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();
}
}
Потребительский поток вызывает waitMsg для получения объекта сообщения. Если список msgList пуст, поток переходит в состояние ожидания, производственный поток создает объект msg physique каждые 3 секунды и помещает его в список msgList. После завершения вызовите notify для пробуждения. потребительский поток для потребления.
Наконец, напомнить снова:wait, notify, notifyAll Класс Thread не является интерфейсом или методом Runnable, а является методом трех собственных классов Object. При вызове этих трех методов текущий поток должен получить блокировку этого объекта.
Последняя практика: маленький лайк, удачи, следите, оставайтесь в молодости, дайте небольшое вознаграждение, и зарплата взлетит до небес. . .