【wait和notify】

news/2024/10/18 14:21:15/

文章目录

  • 前言
  • 一、wait() 方法
    • 1.wait 做的事情:
    • 2.代码实现
    • 3.wait结束等待的条件
  • 二、notify() 方法
    • 1.notify 方法是唤醒等待的线程
    • 2.代码演示
  • 三、notifyAll() 方法
    • 1代码演示:
    • 2.理解 notify 和 notifyAl
  • 四、wait与sleep区别


前言

由于线程之间是抢占式执行的, 因此线程之间执行的先后顺序难以预知.
但是实际开发中有时候我们希望合理的协调多个线程之间的执行先后顺序.
所以我们得想办法控制线程先后

例如:球场上的每个运动员都是独立的 “执行流” , 可以认为是一个 “线程”.
而完成一个具体的进攻得分动作, 则需要多个运动员相互配合, 按照一定的顺序执行一定的动作, 线
程1 先 “传球” , 线程2 才能 “扣篮”.

为了完成这个协调工作,主要涉及到三个办法

  1. wait() / wait(long timeout):让方法进入等待状态(下CPU)
  2. notify():唤醒在当前对象上等待的线程
  3. notifyAll() :随机从等待的线程中唤醒一个

tip:这三都是Object类的方法


一、wait() 方法

1.wait 做的事情:

  • 使当前执行代码的线程进行等待. (把线程放到等待队列中)
  • 释放当前的锁
  • 满足一定条件时被唤醒, 重新尝试获取这个锁.

tip:wait要搭配 synchronized 来使用. 脱离 synchronized 使用 wait 会直接抛出异常,且锁对象必须是同一个,如下图

在这里插入图片描述

2.代码实现

代码如下

        Object object = new Object();Thread t = new Thread(()->{synchronized (object) {System.out.println("wait 前");try {object.wait();//1.解锁  2.进入阻塞等待  3.等待通知唤醒(wait必须在加锁情况)} catch (InterruptedException e) {e.printStackTrace();}System.out.println("wait 后");}});t.start();

3.wait结束等待的条件

  • 其他线程调用该对象的 notify 方法.
  • wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
  • 其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常.

通过上述代码,这样在执行到object.wait()之后就一直等待下去,但是程序肯定不能一直这么等待下去了。这个时候就需要使用到了另外一个方法,唤醒的方法notify()。

二、notify() 方法

1.notify 方法是唤醒等待的线程

  • 方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的
    其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。
  • 如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 “先来后到”)
  • 在notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行
    ,也就是退出同步代码块之后才会释放对象锁 (具体看下面代码)

2.代码演示

    public static void main(String[] args) throws InterruptedException {Object object = new Object();Thread t = new Thread(()->{synchronized (object) {System.out.println("wait 前");try {object.wait();               //1.解锁  2.进入阻塞等待  3.等待通知唤醒(wait必须在加锁情况(需重新获取锁))} catch (InterruptedException e) {e.printStackTrace();}System.out.println("wait 后");}});t.start();Thread.sleep(1000);Thread t1 = new Thread(()->{synchronized (object) {System.out.println("notify 前");object.notify();  //1.解锁  2.进入阻塞等待  3.等待通知唤醒(notify必须在加锁情况)System.out.println("notify 后");}});t1.start();}

执行结果如下
在这里插入图片描述

这里第二行和第三行验证了,notify代码块执行完才会释放当前锁,t1线程才会重新获取到该对象的锁,然后继续执行。这也就达到了控制线程的执行顺序

三、notifyAll() 方法

notify方法只是唤醒某一个等待线程. 使用notifyAll方法可以一次唤醒所有的等待线程.

1代码演示:

public void run() {synchronized (locker) {System.out.println("notify 开始");locker.notifyAll();System.out.println("notify 结束");}}

2.理解 notify 和 notifyAl

notify 只唤醒等待队列中的一个线程. 其他线程还是乖乖等着
在这里插入图片描述

notifyAll 一下全都唤醒, 需要这些线程重新竞争锁:

在这里插入图片描述

四、wait与sleep区别

一个是用于线程之间的通信的一个是让线程阻塞一段时间

在这里插入图片描述
这两方法设计的初衷不同(即解决的问题不同)

wait解决的是线程之间的顺序控制
sleep单纯是为了让线程休眠一会

区别:

  1. wait 需要搭配 synchronized 使用. sleep 不需要.
  2. wait 是 Object 的方法 sleep 是 Thread 的静态方法.


http://www.ppmy.cn/news/590575.html

相关文章

英雄连2一直显示连接relic服务器,英雄连2联机时出现PleaseWait问题的解决方法_英雄连2PleaseWait问题的解决方法_牛游戏网...

联机时出现PleaseWait问题的解决方法: 1. 将Steam和COH2完全关闭 2. 找到Steam文件夹, 找到steam.exe执行文件,在其属性中,选择”兼容性“,取消掉所有打钩的项目,然后单击”更改所有用户的设置“&#xff0…

wait 和 notify

由于线程之间是抢占式执行的,因此线程之间执行的先后顺序难以预知. 但是实际开发中有时候我们希望合理的协调多个线程之间的执行先后顺序 wait( )方法 wait 方法做的事 使当前执行代码的线程进行等待,(把线程放到等待队列中)释放当前的锁满足一定条件…

Welcome ! Please leave word here!

Welcome ! Please leave word here if you have any ideas or proposes.Thank you!

please tell me who you are?

GIT 中提示 please tell me who you are 如果使用git过程中出现了,please tell me who you are , 需要设置一下使用者的身份。 1.git config user.name "username" 2.git config user.email "usernameXXX.com"

notify和wait

public class ListAdd2 {private volatile static List list new ArrayList(); public void add(){list.add("bjsxt");}public int size(){return list.size();}public static void main(String[] args) {final ListAdd2 list2 new ListAdd2();// 1 实例化出来一…

【C++】STL——string类的基本介绍、string常见的使用、string类的接口说明、string类的容量操作

文章目录 1.C语言的字符串2.C标准库中的string类2.1string类2.2string类的常用接口说明2.3string类对象的容量操作 1.C语言的字符串 在C语言中,字符串被表示为字符数组。C语言中的字符串以’\0’字符(null字符或字符串结束符)结尾&#xff0c…

【reactor】响应式实现方法同一个参数多次传入,前两次传入实现分包数据合并,第三次并发传入实现多线程处理

以下是一个使用WebFlux的方法的示例,其中参数可以传入两次,第一次传入后进行一次处理,如果未满足继续执行的要求,则等待第二次传入,第二次传入时再基于第一次处理结果进行第二次处理,第二次处理完成后继续向下执行,如果第一次处理达到要求,则不等待直接向下执行。 imp…

完全零基础,如何学习渗透?

网络渗透这一行,做个脚本小子,使使工具啥的,个把月就学会了,这不难。 很多人把网络渗透简单的理解成就是搞网站,这是大错特错的! 不过这也难怪,Web安全那三招两式,最好教也最好学&…