wait和notify方法
目录
前言
一、wait()方法
wait()做的三件事
让wait()方法结束等待的条件
二、notify()方法
三、notifyAll()方法
总结
四、wait和sleep的对比【面试题】
前言
wait意思是等待,notify的意思是通知,它们的作用是协同多个线程的执行顺序
因为“抢占式执行”让两个线程的执行顺序充满了不确定性,所以我们希望通过wait和notify来控制线程的执行顺序,使线程之间可以更好的配合。
我们需要知道的是这两个方法都是Object(所以类的老祖宗)的方法
一、wait()方法
wait()做的三件事
1.让当前线程阻塞等待(把这个线程的PCB从就绪队列中放到阻塞队列中),准备接受通知
2.释放当前锁(要想使用wait()或者是notify(),就必须搭配synchronized,需要先获取到锁,然后才能谈wait())
3.需要满足一定的条件才能被唤醒,唤醒后重新尝试获取到这个锁
需要注意的是第一点和第二点需要以原子同时完成
让wait()方法结束等待的条件
1.其他线程调用该对象的notify()方法【最主要的用法】
我们已经知道了wait()和notify()都是Object的方法,就是说,如果线程1中的对象1调用了wait()方法,必须要有一个线程2,也调用对象1的notify()方法才能唤醒线程1,如果线程2调用对象2的notify()方法,是不能唤醒线程1的
public class ThreadDemo18 {public static void main(String[] args) throws InterruptedException {Object object=new Object();object.wait();object.notify();}
}
结果为
第一行的灰体带下滑线的意思是非法锁状态
如果没有把wait放到synchronized内部,就能看到这个异常
调用wait的对象和锁对象必须是同一个
public class ThreadDemo18 {public static void main(String[] args) throws InterruptedException {Object object=new Object();synchronized (object){System.out.println("wait之前");object.wait();System.out.println("wait之后");}}
}
结果为
从结果我们可以看出现在这个线程已经进入了阻塞队列中,我们也可以从jconsole.exe看出这个线程正在进行等待
如果我们不对这个程序做什么的话这个线程就会永远等待下去,此时我们需要做点什么来使得这个线程等待状态结束,这里我们引入了notify方法
二、notify()方法
关于notify方法的使用
1.也需要放到synchronized中使用
2.notify操作是一次唤醒一个线程,如果是有多个线程都在等待中,调用notify就相当于是随机唤醒了一个,其它线程保持原状
3.调用notify是通知对方被唤醒,但是调用notify方法的线程并不是立刻释放锁,而是要等待当前的synchronized代码块执行完才释放锁(notify本身不会释放锁)
代码实例
public class ThreadDemo19 {static class WaitTask implements Runnable{private Object locker=null;public WaitTask(Object locker) {this.locker = locker;}@Overridepublic void run() {//进行wait的线程synchronized (locker){System.out.println("wait开始前");try {//直接调用wait,相当于this.wait(),也就是针对WaitTask的对象进行等待//但是我们需要在下面在NotifyTask类中针对同一个对象进行通知//然而,在NotifyTask中拿到WaitTask的对象并不容易locker.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("wait结束");}}}static class NotifyTask implements Runnable{private Object locker=null;public NotifyTask(Object locker) {this.locker = locker;}@Overridepublic void run() {//进行notify的线程synchronized (locker){System.out.println("notify开始前");locker.notify();System.out.println("notify结束");}}}public static void main(String[] args) throws InterruptedException {//所以为了解决上述问题,我们需要专门建一个对象,去负责加锁/通知操作Object locker=new Object();Thread t1=new Thread(new WaitTask(locker));Thread t3=new Thread(new WaitTask(locker));Thread t4=new Thread(new WaitTask(locker));Thread t2=new Thread(new NotifyTask(locker));t1.start();t3.start();t4.start();Thread.sleep(3000);t2.start();}
}
运行结果为
三、notifyAll()方法
notify方法一次只能唤醒一个线程,而notifyAll可以唤醒多个,虽然多个线程都被唤醒了,但这几个线程执行还是有先后顺序的原因是这几个线程还要竞争锁
public void run() {//进行notify的线程synchronized (locker){System.out.println("notify开始前");locker.notifyAll();System.out.println("notify结束");}}
运行结果为
2.wait()等待时间超时
3.其它线程调用该等待线程的interrupted()方法,导致wait抛出InterruptedExpectation异常
总结
notify是一次唤醒一个,而notifyAll是一次唤醒一堆,具体用哪个还要看具体场景,一般来说用的是notify
四、wait和sleep的对比【面试题】
1.sleep操作是指定一个固定时间来阻塞等待,而wait既可以指定时间,也可以无限等待
2.wait可以通过notify或interrupt或时间到来唤醒,sleep通过interrupt或时间到唤醒
3.wait的主要用途是为了协调线程之间的先后顺序,而sleep单纯是让线程休眠,并没涉及到多个线程的配合
wait和notify方法相关推荐
- 对象的notify方法的含义和对象锁释放的三种情况
1,notify的含义 (1)notify一次只随机通知一个线程进行唤醒 (2)在执行了notify方法之后,当前线程不会马上释放该对象锁,呈wait状态的线程也不能马上获得该对象锁, 要等到 ...
- Java线程的挂起与恢复 wait(), notify()方法介绍
一, 什么是线程的挂起与恢复 从字面理解也很简单. 所谓线程挂起就是指暂停线程的执行(阻塞状态). 而恢复时就是让暂停的线程得以继续执行.(返回就绪状态) 二, 为何需要挂起和恢复线程. 我们来看1个 ...
- java wait源码_Java精通并发-透过openjdk源码分析wait与notify方法的本地实现
上一次https://www.cnblogs.com/webor2006/p/11442551.html中通过openjdk从c++的底层来审视了ObjectMonitor的底层实现,这次继续来探究底 ...
- java并发锁获取的方式_Java精通并发-notify方法详解及线程获取锁的方式分析
wait(): 在上一次https://www.cnblogs.com/webor2006/p/11404521.html中对于无参数的wait()方法的javadoc进行了解读,而它是调用了一个参数 ...
- 多线程笔记补充之线程通信wait和notify方法以及Lock和Condition接口的使用
线程通信-wait和notify方法介绍: java.lang.Object类提供类两类用于操作线程通信的方法. wait():执行该方法的线程对象释放同步锁,JVM把该线程存放到等待池中,等待其他的 ...
- java thread.notify_Java Thread notify()方法
Thread类的notify()方法用于唤醒单个线程. 此方法仅为一个等待特定对象的线程提供通知. 如果使用notify()方法并且有多个线程正在等待通知,那么只有一个线程获得通知,而剩下的线程必须等 ...
- 调用notify方法
public class ThreadCommunicateTest implements Runnable{private int cnt=1;@Overridepublic void run(){ ...
- 线程wait和notify方法
一.等待和通知 wait和notify也是为了处理线程调度随机性的问题的,但是这个随机性不太好,还是需要让彼此之间有一个固定的顺序的,join也是一种控制顺序的方式,更倾向于控制线程结束,也是有局限性 ...
- Java学习: wait和notify方法、ThreadLocal
wait方法和notift方法 其实我们之前可能就发现了,Object类还有三个方法我们从来没有使用过,分别是wait().notify()以及notifyAll(),他们其实是需要配合synchro ...
最新文章
- server 2008 中活动目录的迁移
- python 封装_python接口自动化学习笔记(封装方法用于读取excel)
- 浅谈自然语言在科技时代的运用
- 字符串-判断数字的三个方法
- WebSocket服务器和客户端的一对多通知实现
- Linux下读写芯片的I2C寄存器
- C++ Primer 有感(重载操作符)
- sizeof(class)分析
- 赚钱的基本逻辑就是价值交换
- matlab计数器清零,51单片机计数器清零
- SCM供应链管理系统的优点
- 【数据库技术与应用】Part01——数据库系统概述
- mysql identity属性_Mysql中Identity 详细介绍
- jquery 获取上传图片的大小
- 4k视频写入速度要求_4K视频要用什么卡?极速专业存储卡盘点
- 官场直升机 鸿蒙笔著,担当和尚:老衲笔尖无墨水,要从空处想鸿蒙
- 智能电视也进入消费者重视芯片的时代了
- 控制结构(强化):12.阿迪玩游戏
- Y - 献给杭电五十周年校庆的礼物
- 如图,甲乙两人分别在AB两地同时相向而行,于E处相遇后,甲继续向B地行走,乙则休息了14分钟,在继续向A地行走,甲和乙到达B和A后立即折返,又在E处相遇,已知甲每分钟行走60米,乙每分钟行走80米