精通java并发-wait,notify和notifyAll的总结(含案例)
目前CSDN,博客园,简书同步发表中,更多精彩欢迎访问我的gitee pages
wait,notify和notifyAll
总结
在调用wait方法时,线程必须要持有被调用对象的锁,当调用wait方法后,线程就会释放掉该对象的锁(monitor)
在调用Thread类的sleep方法时,线程是不会释放掉对象的锁的
- 当调用wait时,首先需要确保调用了wait方法的线程已经持有了对象的锁
- 当调用wait后,该线程就会释放掉这个对象的锁,然后进入到等待状态(wait set)
- 当线程调用了wait后进入到等待状态时,它就可以等待其他线程调用相同对象的notify或notifyAll方法来使得自己被唤醒
- 一旦这个线程被其他线程唤醒后,该线程就会与其他线程一同开始竞争这个对象的锁(公平竞争);只有当该线程获取到了这个对象的锁后,线程才会继续往下执行
- 调用wait方法的代码片段需要放在一个synchronized块或是synchronized方法中,这样才可以确保线程在调用wait方法前已经获取到了对象的锁
- 当调用对象的notify方法时,它会随机唤醒该对象等待集合(wait set)中的任意一个线程,当某个线程被唤醒后,它就会与其他线程一同竞争对象的锁
- 当调用对象的notifyAll方法时,它会唤醒该对象等待集合(wait set)中的所有线程,这些线程被唤醒后,又会开始竞争对象的锁
- 在某一时刻,只有唯一一个线程可以拥有对象的锁
案例
编写一个多线程程序,实现这样一个目标:
- 存在一个对象,该对象有一个int类型的成员变量counter,该成员变量的初始值为0.
- 创建两个线程,其中一个线程对该对象的成员变量counter增1,另一个线程对该对象的成员变量减1.
- 输出该对象成员变量counter每次变化后的值.
- 最终输出结果应为:101010101010.....
- 创建一个普通类MyObject,有成员变量counter,有一个使counter++的方法和一个使counter--的方法.
public class MyObject {
private int counter;
public synchronized void increase() {
while (counter != 0) {
try {
wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
counter++;
System.out.print(counter);
notify();
}
public synchronized void decrease() {
while (counter == 0) {
try {
wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
counter--;
System.out.print(counter);
notify();
}
}
- 创建一个调用MyObject的increase方法的线程类IncreaseThread
public class IncreaseThread extends Thread {
private MyObject myObject;
public IncreaseThread(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
for (int i = 0; i < 30; ++i) {
try {
Thread.sleep((long)(Math.random() * 1000));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
myObject.increase();
}
}
}
- 创建一个调用MyObject的decrease方法的线程类DecreaseThread
public class DecreaseThread extends Thread {
private MyObject myObject;
public DecreaseThread(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
for (int i = 0; i < 30; ++i) {
try {
Thread.sleep((long)(Math.random() * 1000));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
myObject.decrease();
}
}
}
- 创建一个含main方法的Client类
public class Client {
public static void main(String[] args) {
MyObject myObject = new MyObject();
Thread increaseThread = new IncreaseThread(myObject);
Thread increaseThread2 = new IncreaseThread(myObject);
Thread decreaseThread = new DecreaseThread(myObject);
Thread decreaseThread2 = new DecreaseThread(myObject);
increaseThread.start();
increaseThread2.start();
decreaseThread.start();
decreaseThread2.start();
}
}
- 执行结果

精通java并发-wait,notify和notifyAll的总结(含案例)的更多相关文章
- Java Thread wait, notify and notifyAll Example
Java Thread wait, notify and notifyAll Example Java线程中的使用的wait,notify和nitifyAll方法示例. The Object clas ...
- [译]Java Thread wait, notify和notifyAll示例
Java Thread wait, notify和notifyAll示例 Java上的Object类定义了三个final方法用于不同线程间关于某资源上的锁状态交互,这三个方法是:wait(), not ...
- java wait()和notify()、notifyAll()
图见<JAVA并发编程的艺术>P98-101 这三个方法都是java.lang.Object的方法,用于协调多个线程对共享数据的存取,必须在synchronized语句块中使用!这三个方法 ...
- Java的wait(), notify()和notifyAll()使用小结
wait(),notify()和notifyAll()都是java.lang.Object的方法: wait(): Causes the current thread to wait until an ...
- Java多线程 wait, notify 和 notifyAll
Java的Object类 public class Object { public final native void notify(); public final native void notif ...
- Java的wait(), notify()和notifyAll()使用心得(转)
本篇文章是对java的 wait(),notify(),notifyAll()进行了详细的分析介绍,需要的朋友参考下wait(),notify()和notifyAll()都是java.lang.Obj ...
- java中的notify和notifyAll有什么区别?
先说两个概念:锁池和等待池 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入 ...
- 精通java并发-synchronized关键字和锁
目前CSDN,博客园,简书同步发表中,更多精彩欢迎访问我的gitee pages synchronized关键字和锁 示例代码 public class MyThreadTest2 { public ...
- Java 中 wait, notify 和 notifyAll的正确使用 – 以生产者消费者模型为例
如何使用Wait 尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单.如果你在面试中让应聘者来手写代码,用wait和notify解决生产者消费者问题 ...
随机推荐
- 短短1天我学会了如何修改Butterfly的配置文件
目录 一.修改默认语言 二.创建标签.分类.关于和留言版页面 三.添加搜索框 四.飘带背景 五.使用Valine添加评论功能并支持邮箱提醒 六.收录谷歌.百度 一.修改默认语言 说明:安装Butter ...
- DML_Data Modification_MERGE
DML_8-Data Modification_MERGE (将Source表合并到Target) 语法:MERGE INTO 目标表USING 源表WHEN MATCHED AND ...
- 这一次搞懂Spring代理创建及AOP链式调用过程
文章目录 前言 正文 基本概念 代理对象的创建 小结 AOP链式调用 AOP扩展知识 一.自定义全局拦截器Interceptor 二.循环依赖三级缓存存在的必要性 三.如何在Bean创建之前提前创建代 ...
- cb03a_c++_数据结构_顺序容器_STL_stack
/*cb03a_c++_数据结构_顺序容器_STL_stack堆栈:LIFO--Last In First Out后进先出,用于系统程序设计自适应容器(容器适配器),不是独立的容器,是一个适配器栈适配 ...
- Python 网络爬虫实战:爬取 B站《全职高手》20万条评论数据
本周我们的目标是:B站(哔哩哔哩弹幕网 https://www.bilibili.com )视频评论数据. 我们都知道,B站有很多号称“镇站之宝”的视频,拥有着数量极其恐怖的评论和弹幕.所以这次我们的 ...
- Redis的String探索之路
String是redis最基本的类型,键值对(Key : Value 形式),Redis 的 String 可以包含任何数据,最大能存储 512 MB.(一个键最大能存储 512MB) Redis 的 ...
- leetcode 力扣 两数之和
class Solution: def addTwoNumbers(self, l1, l2): n1 = [] n2 = [] nl = [] while l1.next and l2.next: ...
- RS232/485通信方式 保存和加载时数据的处理
RS232/485通信方式 数据以RS232/485方式通信时,以0xA5作为开始码,以0xAE作为结束码.在开始码和结束码之间的0xA5, 0xAA, 0xAE数据需要进行转码. PC端发送数据时将 ...
- METS介绍
METS介绍 首页 > 关于METS > METS介绍 医护英语水平考试(Medical English Test System, 以下简称:METS)是由教育部考试中心与中国国际 ...
- 02 . Shell变量和逻辑判断及循环使用
Shell变量 系统变量 在命令行提示符直接执行 env.set 查看系统或环境变量.env 显示用户环境变量,set 显示 Shell预先定义好的变量以及用户变量.可以通过 export 导出成用户 ...