1. public class WaitTest {
  2.  
  3. public void testWait(){
  4. System.out.println("Start-----");
  5. try {
  6. wait(1000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. System.out.println("End-------");
  11. }
  12.  
  13. public static void main(String[] args) {
  14. final WaitTest test = new WaitTest();
  15. new Thread(new Runnable() {
  16. @Override
  17. public void run() {
  18. test.testWait();
  19. }
  20. }).start();
  21. }
  22. }
  1. Exception in thread "Thread-0" Start-----
  2. java.lang.IllegalMonitorStateException
  3. at java.lang.Object.wait(Native Method)
  4. at org.knowledge.muti.thread.waitNotify.WaitTest.testWait(WaitTest.java:15)
  5. at org.knowledge.muti.thread.waitNotify.WaitTest$1.run(WaitTest.java:27)
  6. at java.lang.Thread.run(Thread.java:745)
  1.  

这段程序并没有按我们的预期输出相应结果,而是抛出了一个异常。大家可能会觉得奇怪为什么会抛出异常?而抛出的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关键字

  1.  
  1. public class WaitTest {
  2.  
  3. public synchronized void testWait(){
  4. System.out.println("Start-----");
  5. try {
  6. wait(1000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. System.out.println("End-------");
  11. }
  12.  
  13. public static void main(String[] args) {
  14. final WaitTest test = new WaitTest();
  15. new Thread(new Runnable() {
  16. @Override
  17. public void run() {
  18. test.testWait();
  19. }
  20. }).start();
  21. }
  22. }
  1.  
  1.  

所以,通过这个例子,大家应该很清楚,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则唤醒所有的线程,看下面的例子很容易理解这两者的差别:

  1. public synchronized void testWait() {
  2. System.out.println(Thread.currentThread().getName() + " Start-----");
  3.  
  4. try {
  5. wait();
  6. } catch (InterruptedException e) {
  7. // TODO Auto-generated catch block
  8. e.printStackTrace();
  9. }
  10. System.out.println(Thread.currentThread().getName() + " End-----");
  11.  
  12. }
  13.  
  14. public static void main(String[] args) {
  15. NotifyTest obj = new NotifyTest();
  16.  
  17. for (int i = 0; i < 5; i++) {
  18. new Thread() {
  19.  
  20. @Override
  21. public void run() {
  22.  
  23. obj.testWait();
  24. };
  25. }.start();
  26. }
  27.  
  28. synchronized (obj) {
  29.  
  30. obj.notify();
  31. }
  1. Thread.sleep(3000);
  2. System.out.println("-----------分割线-------------");
  1. synchronized (obj) { obj.notifyAll(); } }

    output:

p.p1 { margin: 0; font: 11px Monaco }

  1.  

Thread-0 Start-----

  1.  

Thread-4 Start-----

  1.  

Thread-3 Start-----

  1.  

Thread-2 Start-----

  1.  

Thread-1 Start-----

  1.  

Thread-0 End-----

  1.  

====================notifyAll======

  1.  

Thread-1 End-----

  1.  

Thread-2 End-----

  1.  

Thread-3 End-----

  1.  

Thread-4 End-----

  1.  

高并发之wait notify notifyAll原理详解的更多相关文章

  1. I2C 基础原理详解

    今天来学习下I2C通信~ I2C(Inter-Intergrated Circuit)指的是 IC(Intergrated Circuit)之间的(Inter) 通信方式.如上图所以有很多的周边设备都 ...

  2. 块级格式化上下文(block formatting context)、浮动和绝对定位的工作原理详解

    CSS的可视化格式模型中具有一个非常重要地位的概念——定位方案.定位方案用以控制元素的布局,在CSS2.1中,有三种定位方案——普通流.浮动和绝对定位: 普通流:元素按照先后位置自上而下布局,inli ...

  3. [转]js中几种实用的跨域方法原理详解

    转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...

  4. 【转】VLAN原理详解

    1.为什么需要VLAN 1.1 什么是VLAN? VLAN(Virtual LAN),翻译成中文是“虚拟局域网”.LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络.V ...

  5. LVS原理详解(3种工作方式8种调度算法)--老男孩

    一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...

  6. LVS原理详解(3种工作模式及8种调度算法)

    2017年1月12日, 星期四 LVS原理详解(3种工作模式及8种调度算法)   LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法) 作者:woshiliwentong  发布日期: ...

  7. Namenode HA原理详解(脑裂)

    转自:http://blog.csdn.net/tantexian/article/details/40109331 Namenode HA原理详解 社区hadoop2.2.0 release版本开始 ...

  8. Storm概念、原理详解及其应用(一)BaseStorm

    本文借鉴官文,添加了一些解释和看法,其中有些理解,写的比较粗糙,有问题的地方希望大家指出.写这篇文章,是想把一些官文和资料中基础.重点拿出来,能总结出便于大家理解的话语.与大多数“wordcount” ...

  9. 201709019工作日记--sleep、wait、notify的使用详解

    1. sleep()和wait()的区分 (1)这两个方法来自不同的类分别是,sleep来自Thread类,wait来自Object类. sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在 ...

随机推荐

  1. Hbase的基本原理(与HIVE的区别、数据结构模型、拓扑结构、水平分区原理、场景)

    重点:HBase的基本数据模型.拓扑结构.部署配置方法,并介绍通过命令行和编程方式使用HBase的基本方法. HBase:一种列存储模式与键值对相结合的NoSQL软件,但更多的是使用列存储模式,底层的 ...

  2. 二分查找——没有想象中的容易(详解各种变式,超深度理解,c++)

    int binarySearch(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 注意 while(le ...

  3. python学生管理名片

    name=['刘备','关羽','张飞','赵云','马超'] print('名片管理系统1.0\n1.增加一个新的名片\n2.删除一个名片\n3.修改一个名片\n4.查找一个名片\n5.退出名片管理 ...

  4. css之div中纯文字单行和多行垂直居中

    先上效果图 <html lang="en"> <head> <meta charset="UTF-8"> <meta ...

  5. Zabbix自定义模板监控多个url接口

    一.脚本配置 1.监控脚本 /etc/zabbix/zabbix_agent2.d/scripts/web_site_code_status.sh #!/bin/bash url_discovery( ...

  6. Java并发编程的艺术(九)——闭锁、同步屏障和信号量

    闭锁:CountDownLatch 使用场景 当前线程需要等待若干条线程执行完毕后,才能继续执行的情况. 也可以是若干个步骤执行完毕后的情况. 使用方法 初始化闭锁的时候,填入计数值,然后等待其他线程 ...

  7. memcached session会话共享

    1 安装依赖包yum install libevent livevent-devel nc -y 2 yum 安装memcachedyum install -y memcached 3 启动memec ...

  8. 解压版mysql+免破解版Navicat,好用!

    解压版mysql安装流程 获取mysql压缩包 获取地址: 链接:https://pan.baidu.com/s/1HqdFDQn_6ccPM0gOftApIg 提取码:n19t 获取压缩包后可安装压 ...

  9. js日期格式化-----总结

    1. // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1-4 ...

  10. C++ 虚函数表与多态 —— 多重继承的虚函数表 & 内存布局

    多重继承的虚函数表会有两个虚表指针,分别指向两个虚函数表,如下代码中的 vptr_s_1.vptr_s_2,Son类继承自 Father 和 Mather 类,并且改写了 Father::func_1 ...