前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【多线程】之线程通讯wait和notify的使用

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

作者头像
用户5640963
发布2021-06-09 20:06:17
3580
发布2021-06-09 20:06:17
举报
文章被收录于专栏:卯金刀GG卯金刀GG

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 Files\Java\jdk1.8.0_45\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.3.2\lib\idea_rt.jar=49600:C:\Program Files\JetBrains\IntelliJ IDEA 2018.3.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_45\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_45\jre\lib\rt.jar;C:\hake\manager\comhake\target\classes;C:\program\maven-repository\org\codehaus\groovy\groovy\2.5.6\groovy-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方式

每天进步一点点!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档