【多线程】之线程通讯wait和notify的使用

2021-06-09 20:06:17 浏览数 (1)

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方式

每天进步一点点!

0 人点赞