高并发之wait notify notifyAll原理详解
public class WaitTest {
public void testWait(){
System.out.println("Start-----");
try {
wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End-------");
}
public static void main(String[] args) {
final WaitTest test = new WaitTest();
new Thread(new Runnable() {
@Override
public void run() {
test.testWait();
}
}).start();
}
}
Exception in thread "Thread-0" Start-----
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at org.knowledge.muti.thread.waitNotify.WaitTest.testWait(WaitTest.java:15)
at org.knowledge.muti.thread.waitNotify.WaitTest$1.run(WaitTest.java:27)
at java.lang.Thread.run(Thread.java:745)
这段程序并没有按我们的预期输出相应结果,而是抛出了一个异常。大家可能会觉得奇怪为什么会抛出异常?而抛出的IllegalMonitorStateException异常又是什么?我们可以看一下JDK中对IllegalMonitorStateException的描述:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor
这句话的意思大概就是:线程试图等待对象的监视器或者试图通知其他正在等待对象监视器的线程,但本身没有对应的监视器的所有权。wait方法是一个本地方法,其底层是通过一个叫做监视器锁的对象来完成的。所以上面之所以会抛出异常,是因为在调用wait方式时没有获取到monitor对象的所有权,那如何获取monitor对象所有权?Java中只能通过Synchronized关键字来完成,修改上述代码,增加Synchronized关键字
public class WaitTest {
public synchronized void testWait(){
System.out.println("Start-----");
try {
wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End-------");
}
public static void main(String[] args) {
final WaitTest test = new WaitTest();
new Thread(new Runnable() {
@Override
public void run() {
test.testWait();
}
}).start();
}
}
所以,通过这个例子,大家应该很清楚,wait方法的使用必须在同步的范围内,否则就会抛出IllegalMonitorStateException异常,wait方法的作用就是阻塞当前线程等待notify/notifyAll方法的唤醒,或等待超时后自动唤醒
notify/notifyAll方法
| void notify() | Wakes up a single thread that is waiting on this object's monitor. |
| void notifyAll() | Wakes up all threads that are waiting on this object's monitor. |
有了对wait方法原理的理解,notify方法和notifyAll方法就很容易理解了。既然wait方式是通过对象的monitor对象来实现的,所以只要在同一对象上去调用notify/notifyAll方法,就可以唤醒对应对象monitor上等待的线程了。notify和notifyAll的区别在于前者只能唤醒monitor上的一个线程,对其他线程没有影响,而notifyAll则唤醒所有的线程,看下面的例子很容易理解这两者的差别:
public synchronized void testWait() {
System.out.println(Thread.currentThread().getName() + " Start-----");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " End-----");
}
public static void main(String[] args) {
NotifyTest obj = new NotifyTest();
for (int i = 0; i < 5; i++) {
new Thread() {
@Override
public void run() {
obj.testWait();
};
}.start();
}
synchronized (obj) {
obj.notify();
}
Thread.sleep(3000);
System.out.println("-----------分割线-------------");
synchronized (obj) { obj.notifyAll(); } }
output:
p.p1 { margin: 0; font: 11px Monaco }
Thread-0 Start-----
Thread-4 Start-----
Thread-3 Start-----
Thread-2 Start-----
Thread-1 Start-----
Thread-0 End-----
====================notifyAll======
Thread-1 End-----
Thread-2 End-----
Thread-3 End-----
Thread-4 End-----
高并发之wait notify notifyAll原理详解的更多相关文章
- I2C 基础原理详解
今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...
- 块级格式化上下文(block formatting context)、浮动和绝对定位的工作原理详解
CSS的可视化格式模型中具有一个非常重要地位的概念——定位方案.定位方案用以控制元素的布局,在CSS2.1中,有三种定位方案——普通流.浮动和绝对定位: 普通流:元素按照先后位置自上而下布局,inli ...
- [转]js中几种实用的跨域方法原理详解
转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...
- 【转】VLAN原理详解
1.为什么需要VLAN 1.1 什么是VLAN? VLAN(Virtual LAN),翻译成中文是“虚拟局域网”.LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络.V ...
- LVS原理详解(3种工作方式8种调度算法)--老男孩
一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...
- LVS原理详解(3种工作模式及8种调度算法)
2017年1月12日, 星期四 LVS原理详解(3种工作模式及8种调度算法) LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法) 作者:woshiliwentong 发布日期: ...
- Namenode HA原理详解(脑裂)
转自:http://blog.csdn.net/tantexian/article/details/40109331 Namenode HA原理详解 社区hadoop2.2.0 release版本开始 ...
- Storm概念、原理详解及其应用(一)BaseStorm
本文借鉴官文,添加了一些解释和看法,其中有些理解,写的比较粗糙,有问题的地方希望大家指出.写这篇文章,是想把一些官文和资料中基础.重点拿出来,能总结出便于大家理解的话语.与大多数“wordcount” ...
- 201709019工作日记--sleep、wait、notify的使用详解
1. sleep()和wait()的区分 (1)这两个方法来自不同的类分别是,sleep来自Thread类,wait来自Object类. sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在 ...
随机推荐
- 第9.7节 Python使用write函数写入文件内容
一. 语法 write(data) data为要写入的数据,可以为字符串str类型,也可以是bytes类型. 返回值为实际写入的数据数,在写入数据为str类型时,该数据为实际写入的UNIOCODE字符 ...
- Python中str类型的字符串写入二进制文件时报TypeError错的处理方式
在用二进制模式打开文件情况下,写入一个str对象时报错:TypeError: a bytes-like object is required, not 'str' 出现该问题是因为Python严格区分 ...
- PyQt(Python+Qt)学习随笔:QTableView的gridStyle属性
老猿Python博文目录 老猿Python博客地址 概述 gridStyle属性用于控制视图数据网格的样式,此属性只有在showGrid属性为True时才有作用. gridStyle属性取值含义 gr ...
- sql bool盲注
[CISCN2019 总决赛 Day2 Web1]Easyweb 考察: robots.txt image.php?bak文件泄露,image.php.bak可以下载别的不大行 盲注 php日志挂马 ...
- Python接口测试-使用requests模块发送GET请求
本篇主要记录下使用python的requests模块发送GET请求的实现代码. 向服务器发送get请求:无参数时:r = requests.get(url)带params时:r = requests. ...
- SpringCloud-服务间通信方式
接下来在整个微服务架构中,我们比较关心的就是服务间的服务改如何调用,有哪些调用方式? 总结:在springcloud中服务间调用方式主要是使用 http restful方式进行服务间调用 1. 基于R ...
- AtCoder Regular Contest 108
Contest Link Official Editorial A - Sum and Product Given are integers \(S\) and \(P\) . Is there a ...
- 题解-CF101D Castle
题面 CF101D Castle 给一棵 \(n\) 个节点的带权树,求一种遍历方案,从 \(1\) 出发,每条边走两次,走过所有点,第一次经过每个节点的平均时间最小.输出这个平均时间. 数据范围:\ ...
- MySQL技术内幕InnoDB存储引擎(二)——InnoDB存储引擎
1.概述 是一个高性能.高可用.高扩展的存储引擎. 2.InnoDB体系架构 InnoDB存储引擎主要由内存池和后台线程构成. 其中,内存池由许多个内存块组成,作用如下: 维护所有进程和线程需要访问的 ...
- 传输层-Transport Layer(上):传输层的功能、三次握手与四次握手、最大-最小公平、AIMD加法递增乘法递减
第六章 传输层-Transport Layer(上) 6.1传输层概述 在之前的几章内容中,我们自底向上的描述了计算机网络的各个层次,还描述了一些处于不同层次下的经典网络协议(如以太网.无线局域网.或 ...