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, ...
随机推荐
- 知方可补不足~SQL数据库用户的克隆,SQL集群的用户同步问题
我们知道在为sqlserver建立功能数据库时,通过会为库再建立一个登陆名,而这个登陆名时,只用来管理这个数据库,这是安全的,正确的.
- 怎样在Java中实现基本数据类型与字符之间的转换
摘要:在我们对Java的学习当中数据类型之间的转换,是我们常见的事,我们也都知道基本数据类型之间有自动转换和强制转换,在int . short . long .float .double之间的转 ...
- 使用ApplicationLoader中出现报错:The IPA is invalid. It does not inlude a Payload directory
问题处理方法: 1.将achieve的.app后缀的软件包放在一个payload的文件夹中 2.压缩该文件夹,改变.zip后缀为.ipa 3.使用applicationLoader上传该文件
- Android设计模式—策略模式
1.策略模式概念 定义一系列算法,把他们独立封装起来,并且这些算法之间可以相互替换.策略模式主要是管理一堆有共性的算法,客户端可以根据需要,很快切换这些算法,并且保持可扩展性. 策略模式的本质:分离算 ...
- 人工智能-有限状态机(FSM)的学习
首先声明:此文源于本人最近学习的一本书 <游戏人工智能编程案例精粹> FSM的定义: 一个有限状态机是一个设备,或是一个设备模型,具有有限数量的状态,它可以在任何给定的时间根据输入进行操作 ...
- 【转】来自《轻松scrum之旅》的敏捷开发总结
敏捷开发的核心价值观是,软件开发最重要的是给用户提供有价值的.可以工作的软件.如何保证提供有价值的软件,是通过反馈机制来完成的.这一点,我们体会很深.自从采用敏捷开发以后,我们比以前更有意识地希望得到 ...
- Java Swing界面编程(1)
写多了jsp,对于页面式的系统已经写烦了,本人也開始着手于java swing的学习,作为菜鸟,仅想用博客记录下我的swing学习的历程.话不多说,首先開始我的第一个窗体化程序. 下面给出源码: pa ...
- C#-将控件动态添加到选项卡页tablepage
tabPage1.Controls.Add(new Button()); 实例: Button cp = new Button(); cp.text="test";cp.Click ...
- RHEL 7特性说明(七):编译程序及工具
转载自:RedHat https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/7/html/7.0_Release ...
- [Effective C++ --014]在资源管理类中小心copying行为
第一节 <背景> 条款13中讲到“资源取得的时机便是初始化时机”并由此引出“以对象管理资源”的概念.通常情况下使用std中的auto_ptr(智能指针)和tr1::shared_ptr(引 ...