wait(...) notify() notifyAll()
简介
wait、notify、notifyAll是Java中3个与线程有关的方法,它们都是Object类中的方法。
其中,wait方法有3个重载形式:
1、wait()
2、wait(long timeout)
3、wait(long timeout, int nanos)
这5个方法都是final方法。其中,wait(long timeout)、notify()、notifyAll()都是native方法。
另外,3个wait方法均有InterruptedException抛出,而notify和notifyAll方法没有异常抛出。
这3类方法的语义大致如下所述:
wait |
如果调用了某对象的wait方法,那么持有该对象的锁的线程会放弃对该对象的锁定,然后等待再次获得该对象的锁。 |
notify |
如果调用了某对象的notify方法,那么某个在等待获得该对象的锁的线程会被唤醒继续执行。 |
notifyAll |
与notify稍有不同的是,notifyAll方法会唤醒在该对象上等待的所有线程。 |
特别提醒的是,wait、notify、notifyAll方法都必须在同步方法或同步语句块内部调用。这是因为要调用这3类方法,必须让当前线程持有方法所属的对象的锁,否则就会抛出IllegalMonitorStateException。
例如,下面的代码是错误的,因为在调用对象a的wait()方法之前,当前线程没有持有对象a的锁:
public class A { public void m() throws InterruptedException { this.wait(); } public static void main(String[] args) { A a = new A(); try { a.m(); } catch (Throwable t) { t.printStackTrace(); } } } |
运行上面的代码,必然抛出如下异常:
java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:485) at A.m(A.java:4) at A.main(A.java:10) |
正确的写法,是给A类的m方法加上synchronized修饰符,这样,当执行到m方法内部的“this.wait()”语句时,当前线程已经持有了对象a的锁,调用它的wait()方法就不会抛出异常了。
有了这些知识点,我们来具体看一下这3类方法。
wait(long timeout)
该方法的声明语句如下:
public final native void wait() throws InterruptedException; |
它的作用是:调用某对象的wait(long timeout)方法会造成当前线程放弃该对象的锁,转到等待状态,直到其它线程调用了该对象的notify()或notifyAll()方法,或者指定的时间(timeout)被耗尽。
该方法的参数timeout的单位是毫秒。值得注意的是,即便timeout参数所指定的时间被耗尽,当前线程也不是一定就会恢复执行,这要看时间耗尽时是否有其它线程持有该对象的锁。
参数timeout不能是负数,否则会抛出IllegalArgumentException。timeout为0时,表示无限等待,时间不会耗尽,只能等别的线程来唤醒自己。
wait()、wait(long timeout, int nanos)
这两个方法的声明语句如下:
public final void wait() throws InterruptedException { wait(0); } public final void wait(long timeout, int nanos) throws InterruptedException { if (timeout < 0) throw new IllegalArgumentException( “timeout value is negative”); if (nanos < 0 || nanos > 999999) throw new IllegalArgumentException( “nanosecond timeout value out of range”); if (nanos >= 500000 || (nanos != 0 && timeout == 0)) timeout++; wait(timeout); } |
从代码上看,并结合wait(long timeout)的介绍,其逻辑意义就很明显了,不多做介绍。
notify()、notifyAll()
这两个方法的声明语句如下:
public final native void notify(); public final native void notifyAll(); |
notify和notifyAll的区别是,notifyAll会唤醒所有在某对象上等待的线程继续执行,但实际上,无论调用notify还是调用notifyAll,结果都只能有一个线程拿到锁并真的继续执行。
需要注意的是,当notify或notifyAll被调用成功后,被唤醒的线程实际上已经进入synchronized方法或代码块内部,这一点非常重要。
wait(...) notify() notifyAll()的更多相关文章
- java 多线程之wait(),notify,notifyAll(),yield()
wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每个对像都有wait(),notify(),notifyAll()的功能.因为都个对像都 ...
- java中的wait(),notify(),notifyAll(),synchronized方法
wait(),notify(),notifyAll()三个方法不是Thread的方法,而是Object的方法.意味着所有对象都有这三个方法,因为每个对象都有锁,所以自然也都有操作锁的方法了.这三个方法 ...
- java 多线程(wait/notify/notifyall)
package com.example; public class App { /* wait\notify\notifyAll 都属于object的内置方法 * wait: 持有该对象的线程把该对象 ...
- Java多线程8:wait()和notify()/notifyAll()
轮询 线程本身是操作系统中独立的个体,但是线程与线程之间不是独立的个体,因为它们彼此之间要相互通信和协作. 想像一个场景,A线程做int型变量i的累加操作,B线程等待i到了10000就打印出i,怎么处 ...
- 使用Object的wait,notify,notifyAll做线程调度
我们知道java中的所有类的祖先都是Object,Object类有四个个方法wait(),wait(long timeout),notify(),notifyAll(),这四个方法可以用来做线程的调度 ...
- Java多线程之wait(),notify(),notifyAll()
在多线程的情况下,因为同一进程的多个线程共享同一片存储空间,在带来方便的同一时候,也带来了訪问冲突这个严重的问题.Java语言提供了专门机制以解决这样的冲突,有效避免了同一个数据对象被多个线程同一时候 ...
- Java多线程的wait(),notify(),notifyAll()
在多线程的情况下.因为多个线程与存储空间共享相同的过程,同时带来的便利.它也带来了访问冲突这个严重的问题. Java语言提供了一种特殊的机制来解决这类冲突,避免同一数据对象由多个线程在同一时间访问. ...
- Java多线程学习之wait、notify/notifyAll 详解
1.wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写. 2.wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关 ...
- 【java线程系列】java线程系列之线程间的交互wait()/notify()/notifyAll()及生产者与消费者模型
关于线程,博主写过java线程详解基本上把java线程的基础知识都讲解到位了,但是那还远远不够,多线程的存在就是为了让多个线程去协作来完成某一具体任务,比如生产者与消费者模型,因此了解线程间的协作是非 ...
- Java多线程:wait(),notify(),notifyAll()
1. wait(),notify(),notifyAll() 2. wait() 2.1. wait() 2.2. wait(long timeout) 2.3. wait(long timeout, ...
随机推荐
- ecshop如何去除后台左侧云服务中心菜单
介绍一下如何去除后台云服务中心菜单: 打开admin/templates/menu.htm,把539行的 document.getElementById("menu-ul").in ...
- ThinkPHP中URL解析原理,以及URL路由使用教程!
几个概念: THINKPHP 是一个MVC框架,使用PATHINFO解析出分组名,模块名,方法名,以及参数. PATHINFO:就是 http://localhost/index.php/Home/I ...
- 【转】于request.getSession(true/false/null)的区别
http://blog.csdn.net/gaolinwu/article/details/7285783 关于request.getSession(true/false/null)的区别 一.需求原 ...
- C#_数据库基本交互
//app.config <?xml version="1.0" encoding="utf-8" ?> <configuration> ...
- 文本框的placeholder属性
在文本框中添加placeholder属性,用于文本框处于未输入状态时,模糊显示输入提示,当用户进行输入时,不需要删除该提示文字. 如: <input type="text" ...
- [置顶] c++,vc6.0,中友元函数,无法访问私有字段(private)的问题(problem),cannot access private member declared in class 'Date'
c++,vc6.0,中友元函数,无法访问私有字段(private)的问题(problem),cannot access private member declared in class 'Date' ...
- Python 文件操作模块 shutil 详解
1.导入模块 shutil import shutil 2.shutil方法 2.1 shutil.copy(src,dst) //将 src 复制到 dst 保留文件权限 例:将Alan复制到 ...
- PV信号量的一些理解
进程通常分为就绪.运行和阻塞三个工作状态.三种状态在某些条件下可以转换,三者之间的转换关系如下: 进程三个状态之间的转换就是靠PV操作来控制的.PV操作主要就是P操作.V操作和信号量.其中信号量起 ...
- 关于git的基本命令
git环境的搭建这里就先不说.本篇主要是普通开发工作者在开发过程中所使用的命令. 作为开发者,别人搭建git服务器之后,你呢就配置个人的客户端: 设置Git的配置变量,这个是一次性的工作.即这些设置会 ...
- C语言中 指针、引用和取值
指针是一个存储计算机内存地址的变量.从指针指向的内存读取数据称作指针的取值.指针可以指向某些具体类型的变量地址,例如int.long和double.指针也可以是void类型.NULL指针和未初始化指针 ...