目前CSDN,博客园,简书同步发表中,更多精彩欢迎访问我的gitee pages

wait,notify和notifyAll

总结

  • 在调用wait方法时,线程必须要持有被调用对象的锁,当调用wait方法后,线程就会释放掉该对象的锁(monitor)

  • 在调用Thread类的sleep方法时,线程是不会释放掉对象的锁的

  1. 当调用wait时,首先需要确保调用了wait方法的线程已经持有了对象的锁
  2. 当调用wait后,该线程就会释放掉这个对象的锁,然后进入到等待状态(wait set)
  3. 当线程调用了wait后进入到等待状态时,它就可以等待其他线程调用相同对象的notify或notifyAll方法来使得自己被唤醒
  4. 一旦这个线程被其他线程唤醒后,该线程就会与其他线程一同开始竞争这个对象的锁(公平竞争);只有当该线程获取到了这个对象的锁后,线程才会继续往下执行
  5. 调用wait方法的代码片段需要放在一个synchronized块或是synchronized方法中,这样才可以确保线程在调用wait方法前已经获取到了对象的锁
  6. 当调用对象的notify方法时,它会随机唤醒该对象等待集合(wait set)中的任意一个线程,当某个线程被唤醒后,它就会与其他线程一同竞争对象的锁
  7. 当调用对象的notifyAll方法时,它会唤醒该对象等待集合(wait set)中的所有线程,这些线程被唤醒后,又会开始竞争对象的锁
  8. 在某一时刻,只有唯一一个线程可以拥有对象的锁

案例

编写一个多线程程序,实现这样一个目标:

  1. 存在一个对象,该对象有一个int类型的成员变量counter,该成员变量的初始值为0.
  2. 创建两个线程,其中一个线程对该对象的成员变量counter增1,另一个线程对该对象的成员变量减1.
  3. 输出该对象成员变量counter每次变化后的值.
  4. 最终输出结果应为: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的总结(含案例)的更多相关文章

  1. Java Thread wait, notify and notifyAll Example

    Java Thread wait, notify and notifyAll Example Java线程中的使用的wait,notify和nitifyAll方法示例. The Object clas ...

  2. [译]Java Thread wait, notify和notifyAll示例

    Java Thread wait, notify和notifyAll示例 Java上的Object类定义了三个final方法用于不同线程间关于某资源上的锁状态交互,这三个方法是:wait(), not ...

  3. java wait()和notify()、notifyAll()

    图见<JAVA并发编程的艺术>P98-101 这三个方法都是java.lang.Object的方法,用于协调多个线程对共享数据的存取,必须在synchronized语句块中使用!这三个方法 ...

  4. Java的wait(), notify()和notifyAll()使用小结

    wait(),notify()和notifyAll()都是java.lang.Object的方法: wait(): Causes the current thread to wait until an ...

  5. Java多线程 wait, notify 和 notifyAll

    Java的Object类 public class Object { public final native void notify(); public final native void notif ...

  6. Java的wait(), notify()和notifyAll()使用心得(转)

    本篇文章是对java的 wait(),notify(),notifyAll()进行了详细的分析介绍,需要的朋友参考下wait(),notify()和notifyAll()都是java.lang.Obj ...

  7. java中的notify和notifyAll有什么区别?

    先说两个概念:锁池和等待池 锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入 ...

  8. 精通java并发-synchronized关键字和锁

    目前CSDN,博客园,简书同步发表中,更多精彩欢迎访问我的gitee pages synchronized关键字和锁 示例代码 public class MyThreadTest2 { public ...

  9. Java 中 wait, notify 和 notifyAll的正确使用 – 以生产者消费者模型为例

    如何使用Wait 尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单.如果你在面试中让应聘者来手写代码,用wait和notify解决生产者消费者问题 ...

随机推荐

  1. 01---eclipse使用

    一.eclipse快捷键 1.alt+? 或 alt+/:自动补全代码或者提示代码,可用于main函数(main).输出函数(syso)等 2.ctrl+1:错误提示 3.ctrl+/:自动注释当前行 ...

  2. a标签伪类link,hover,active,visited,focus区别

    <div id="content"> <h3><a class="a1" href="#">a标签伪类l ...

  3. 如何解压bz2后缀的压缩文件

    .bz2 解压1:bzip2 -d FileName.bz2 解压2:bunzip2 FileName.bz2 压缩: bzip2 -z FileName .tar.bz2 解压:tar jxvf F ...

  4. excel如何快速汇总多个类别的总和?

    这个需求是一位在当前抗疫一线的朋友提出的,和各位分享一下. 需求情况 因为众所周知的原因,他每天都需要为照顾的小区居民购买.运送生活物资.小区居民通过表单的形式提交自己每日的需求,最终汇总到一张exc ...

  5. java中的excel操作

    导入jxl.jar包: 下载个jxl.jar包,然后这个包放在什么位置都行,在你的项目中导入这个包就可以.   具体做法: 项目上右键,点击“属性”, 类别那里选择”库“,点击"添加jar文 ...

  6. 深入理解JVM(③)ZGC收集器

    前言 ZGC是一款在JDK11中新加入的具有实验性质的低延迟垃圾收集器,目前仅支持Linux/x86-64.ZGC收集器是一款基于Region内存布局的,(暂时)不设分代的,使用了读屏障.染色指针和内 ...

  7. 一对多分页的SQL到底应该怎么写?

    1. 前言 MySQL一对多的数据分页是非常常见的需求,比如我们要查询商品和商品的图片信息.但是很多人会在这里遇到分页的误区,得到不正确的结果.今天就来分析并解决这个问题. 2. 问题分析 我们先创建 ...

  8. 搞定ReentrantReadWriteLock 几道小小数学题就够了

    | 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it ...

  9. python实现简单的SVM

    # -*- coding: utf-8 -*- from sklearn.svm import SVC import numpy as np print(X.shape,Y.shape) X = np ...

  10. unable to load script from assets 'index.android bundle'

    在Android手机上运行React-native项目时 报错:unable to load script from assets 'index.android bundle'  ,make sure ...