1、定义 等待/通知机制,是指一个线程A调用了对象object的wait()方法进入等待状态,而另一个线程B调用了对象object的notify或者notifyAll()方法,线程A收到通知后从对象O的wait()方法返回,进而还行后续操作。 使用wait和notify方法实现线程之间的通信,这两个方法是Object类的方法。 注意细节: 1.1 调用wait()方法,会释放锁,线程状态由RUNNING->WAITNG,当前线程进入对象等待; 1.2 调用notify()/notifyAll()方法不会立马释放锁,notify()方法是将等待队列中的线程移到同步队列中,而notifyAll()则是全部移到同步队列中, 被移出的线程状态WAITING-->BLOCKED; 重点注意,等待队列和同步队列的转换;wait()后进入等待队列;notify()/notifyAll(),线程进入同步队列; 1.3 当前调用notify()/notifyAll()的线程释放锁了才算释放锁,才有机会唤醒wait线程; 1.4 从wait()返回的前提是必须获得调用对象锁,也就是说notify()与notifyAll()释放锁之后,wait()进入BLOCKED状态,如果其他线程 有竞争当前锁的话,wait线程继续争取锁资格。可以理解为,从同步队列中的线程抢占锁执行; 1.5 使用wait()、notify()、notifyAll()方法时需要先调对象加锁。这就是跟synchronized关键字配置使用; 2、代码运行过程
代码语言:javascript复制package hake.waitnotifydemo;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: Liu Yue
* @Descripition:
* @Date; Create in 2021/6/1 10:35
**/
public class Demo {
private static volatile List list=new ArrayList();
public static void main(String[] args) {
final Object lock = new Object();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
System.out.println("thread - 1 线程启动 ***************************");
for (int i = 0;i < 10; i ){
list.add("thread - 1 - " i);
System.out.println("当前线程" Thread.currentThread().getName() "添加了一个元素");
try{
Thread.sleep(500);
if (list.size()==5){
System.out.println("发出唤醒通知********************");
lock.notify();
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
},"thread - 1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
System.out.println("thread - 2 启动 -------------------------------");
if(list.size() != 5){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前线程:" Thread.currentThread().getName() "收到通知线程停止..");
throw new RuntimeException();
}
}
},"thread - 2");
thread2.start();
thread1.start();
}
}
运行代码结果
代码语言:javascript复制"C:Program FilesJavajdk1.8.0_45binjava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2018.3.2libidea_rt.jar=49600:C:Program FilesJetBrainsIntelliJ IDEA 2018.3.2bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_45jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_45jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_45jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_45jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_45jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_45jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_45jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_45jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_45jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_45jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_45jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_45jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_45jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_45jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_45jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_45jrelibjce.jar;C:Program FilesJavajdk1.8.0_45jrelibjfr.jar;C:Program FilesJavajdk1.8.0_45jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_45jrelibjsse.jar;C:Program FilesJavajdk1.8.0_45jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_45jrelibplugin.jar;C:Program FilesJavajdk1.8.0_45jrelibresources.jar;C:Program FilesJavajdk1.8.0_45jrelibrt.jar;C:hakemanagercomhaketargetclasses;C:programmaven-repositoryorgcodehausgroovygroovy2.5.6groovy-2.5.6.jar" hake.waitnotifydemo.Demo
thread - 2 启动 -------------------------------
thread - 1 线程启动 ***************************
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
发出唤醒通知********************
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
当前线程thread - 1添加了一个元素
当前线程:thread - 2收到通知线程停止..
Exception in thread "thread - 2" java.lang.RuntimeException
at hake.waitnotifydemo.Demo$2.run(Demo.java:54)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code 0
首先启动thread2线程,使得thread2线程处于等待状态,然后当集合等于5的时候,thread1向thread2线程发出通知,但是并不会释放锁,所以当thread1执行 完毕后,thread2线程才会向下执行。
注意:wait()/nofity()/notifyAll()/ 使用前必须加锁;
相似的功能:
Condition配合Lock实现的等待/通知模式(下一步解析)
LockSupport阻塞park与唤醒unpark方式
每天进步一点点!