目前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. .Net Core微服务入门全纪录(三)——Consul-服务注册与发现(下)

    前言 上一篇[.Net Core微服务入门全纪录(二)--Consul-服务注册与发现(上)]已经成功将我们的服务注册到Consul中,接下来就该客户端通过Consul去做服务发现了. 服务发现 同样 ...

  2. 其他函数-web_get_int_property

    用于记录http响应的信息.这个函数在调试脚本的常用,但是在实际压力测试中请将这些注释 使用这个函数可以获取到的信息有: 1.HTTP_INFO_RETURN_CODE:返回HTTP响应码 2.HTT ...

  3. android中getWidth()和getMeasuredWidth()之间的区别

    先给出一个结论:getMeasuredWidth()获取的是view原始的大小,也就是这个view在XML文件中配置或者是代码中设置的大小.getWidth()获取的是这个view最终显示的大小,这个 ...

  4. Jmeter各种组件

    断言 用于检查测试中得到的响应数据等是否符合预期,用以保证性能测试过程中的数据交互与预期一致 参数化关联 参数化:指对每次发起的请求,参数名称相同,参数值进行替换,如登录三次系统,每次用不同的用户名和 ...

  5. docker配置国内镜像地址,解决无法pull镜像问题docker: Error response from daemon

    问题: 执行命令 $ docker run -it --rm -p 8888:8080 tomcat:8.5.32 报错 Unable to find image 'tomcat:8.5.32' lo ...

  6. JavaWeb网上图书商城完整项目--day02-14.登录功能的login页面处理

    1.现在注册成功之后,我们来到登录页面,登录页面在于 在登录页面.我们也需要向注册页面一样对登录的用户名.密码 验证码等在jsp页面中进行校验,校验我们单独放置一个login.js文件中进行处理,然后 ...

  7. python的一些基础知识

    一.函数介绍 二.模块与包 三.面向对象介绍 四.网络编程基础应用了解 五.基于MySQL对数据库的理解及基础操作 六.粗浅学习的前端知识整理

  8. 关于MySQL事务和存储引擎常见FAQ

    1.什么是事务? 事务就是「一组原子性的SQL查询」,或者说一个独立的工作单元.如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询.如果其中有任何一条语句因为崩溃或其他原因无法 ...

  9. python用类的方式创建线程---自创建类

    用类的方式创建线程---自创建类 import threadingimport time class MyThread(threading.Thread):#自建MyThread类继承threadin ...

  10. 资深阿里程序员一一为你解刨Web前端知识体系结构,付出与收获成正比!

    只要接触过前端,都会指导web前端的知识主要由三部分组成:分别为静态html,样式css,动态javascript(简称js)这三大部分组成.其三部分组成的一个体系的复杂程度不亚于其他一门技术的复杂程 ...