首先我们来看一张图,这张图描述了线程操作的几个步骤。

图已经描述的很清楚了,这里除了wait()之外,其他的前面都已经接触过了。
这一章我们主要来说一下和wait()相关的操作,其实和wait()相关的还有另外两个函数notity()和notifyAll()。
这三个函数都是Object类里的方法
wait():使调用此方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒
notify():随机唤醒等待队列中等待同一个共享资源的“一个”线程,并使该线程退出等待队列,进入可运行状态,也就是说notofy()通知唤醒一个线程。
notifyAll():使所有正在等待队列中等待同一个共享资源的“全部”线程从等待状态退出,进入可运行状态。
注意:notify()和notifyAll()后并不是直接就释放锁的,而是等notify()后的代码执行完毕后才释放锁。而且这三个方法都必须在synchronize代码块里执行,否则会报错。
 
每个对象都有两个队列,一个是就绪队列,一个是阻塞队列。就绪队列存储了将要获得锁的线程,阻塞队列存储了所有被阻塞的线程。一个线程被唤醒后,才会进入就绪队列,等待CPU的调度,反之,一个线程被wait()之后,线程就进入了阻塞队列,等待下一次被唤醒。
 
线程会释放锁的三种情况:
1.线程任务执行完毕,释放锁。
2.线程调用wait()方法,释放锁。
3.线程执行过程中发生异常,释放锁。
 
生产-消费者模式:
单生产者,单消费者demo:
 
①.生产者:
  1. package com.multiThread.bean;
  2. publicclass P {
  3. privateObject lock;
  4. public P(Object lock){
  5. this.lock = lock;
  6. }
  7. publicvoidSetValue(){
  8. try{
  9. synchronized(lock){
  10. if(!ValueObject.value.equals("")){
  11. lock.wait();
  12. }
  13. String value =System.currentTimeMillis()+"_"+System.nanoTime();
  14. System.out.println("set值为:"+ value);
  15. ValueObject.value = value;
  16. lock.notify();
  17. }
  18. }catch(Exception e){
  19. e.printStackTrace();
  20. }
  21. }
  22. }
②.消费者
  1. package com.multiThread.bean;
  2. publicclass C {
  3. privateObject lock;
  4. public C(Object lock){
  5. this.lock = lock;
  6. }
  7. publicvoid getValue(){
  8. try{
  9. synchronized(lock){
  10. if(ValueObject.value.equals("")){
  11. lock.wait();
  12. }
  13. System.out.println("get的值:"+ValueObject.value);
  14. ValueObject.value ="";
  15. lock.notify();
  16. }
  17. }catch(Exception e){
  18. e.printStackTrace();
  19. }
  20. }
  21. }
③.生产者线程类
  1. package com.multiThread.thread;
  2. import com.multiThread.bean.P;
  3. publicclassThreadPimplementsRunnable{
  4. private P p;
  5. publicThreadP(P p){
  6. this.p = p;
  7. }
  8. @Override
  9. publicvoid run(){
  10. while(true){
  11. p.SetValue();
  12. }
  13. }
  14. }
④.消费者线程类
  1. package com.multiThread.thread;
  2. import com.multiThread.bean.C;
  3. publicclassThreadCimplementsRunnable{
  4. private C c;
  5. publicThreadC(C c){
  6. this.c = c;
  7. }
  8. @Override
  9. publicvoid run(){
  10. while(true){
  11. c.getValue();
  12. }
  13. }
  14. }
⑤.测试类
  1. package com.multiThread.test.productionConsumption;
  2. import com.multiThread.bean.C;
  3. import com.multiThread.bean.P;
  4. import com.multiThread.thread.ThreadC;
  5. import com.multiThread.thread.ThreadP;
  6. /**
  7. * 等待、通知机制
  8. */
  9. publicclassProduceCustomTest{
  10. publicstaticvoid main(String[] args){
  11. Object lock =newObject();
  12. P p =new P(lock);
  13. C c =new C(lock);
  14. ThreadP tp =newThreadP(p);
  15. ThreadC tc =newThreadC(c);
  16. Thread t1 =newThread(tp);
  17. Thread t2 =newThread(tc);
  18. t1.start();
  19. t2.start();
  20. }
  21. }
执行结果:
  1. set值为:1466176983137_22743411842275
  2. get的值:1466176983137_22743411842275
  3. set值为:1466176983137_22743412731096
  4. get的值:1466176983137_22743412731096
  5. set值为:1466176983137_22743412952232
  6. get的值:1466176983137_22743412952232
  7. set值为:1466176983137_22743413140860
  8. get的值:1466176983137_22743413140860
  9. .
  10. .
  11. .
可见生产者和消费者是交替执行的。
这里仅仅是单生产者和消费者。如果是多生产者和消费者会正常运行吗?
答案是否定的。因为notify()之后是随机唤醒一个线程,如果生产者唤醒的是生产者,那么就会一直处于wait(),造成死锁。
解决问题的方法:
    将notify()方法换成notifyAll()
 
 
 
 
 
 
 
 
 

多线程(五)~ wait/notify机制(等待/通知)的更多相关文章

  1. Java多线程学习(四)等待/通知(wait/notify)机制

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79690279 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  2. Java并发读书笔记:线程通信之等待通知机制

    目录 synchronized 与 volatile 等待/通知机制 等待 通知 面试常问的几个问题 sleep方法和wait方法的区别 关于放弃对象监视器 在并发编程中,保证线程同步,从而实现线程之 ...

  3. 超强图文|并发编程【等待/通知机制】就是这个feel~

    你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...

  4. 十六、Condition等待通知

    一.简介 我们可以使用syncronized和wait,notify实现等待通知.而syncronized的高级实现Lock,也可以实现等待通知,需要构造Condition的实例对象. JDK文档:h ...

  5. java 多线程:线程通信-等待通知机制wait和notify方法;(同步代码块synchronized和while循环相互嵌套的差异);管道通信:PipedInputStream;PipedOutputStream;PipedWriter; PipedReader

    1.等待通知机制: 等待通知机制的原理和厨师与服务员的关系很相似: 1,厨师做完一道菜的时间不确定,所以厨师将菜品放到"菜品传递台"上的时间不确定 2,服务员什么时候可以取到菜,必 ...

  6. java多线程系列(三)---等待通知机制

    等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...

  7. Java Concurrency - wait & notify, 等待通知机制

    生产者消费者问题是一个常见的多线程同步案例:一组生产者线程和一组消费者线程共享一个初始状态为空.大小为 N 的缓冲区.只有当缓冲区没满的时候,生产者才能把消息放入缓冲区,否则必须等待:只有缓冲区不空的 ...

  8. Java多线程之三volatile与等待通知机制示例

    原子性,可见性与有序性 在多线程中,线程同步的时候一般需要考虑原子性,可见性与有序性 原子性 原子性定义:一个操作或者多个操作在执行过程中要么全部执行完成,要么全部都不执行,不存在执行一部分的情况. ...

  9. 《java多线程编程核心技术》不使用等待通知机制 实现线程间通信的 疑问分析

    不使用等待通知机制 实现线程间通信的 疑问分析 2018年04月03日 17:15:08       ayf 阅读数:33 编辑 <java多线程编程核心技术>一书第三章开头,有如下案例: ...

  10. java使用wait(),notify(),notifyAll()实现等待/通知机制

    public class WaitNotify { static boolean flag=true; static Object lock=new Object(); static class Wa ...

随机推荐

  1. python学习之路---day23--模块

    模块基本小结if __name__ == '__main__':一:import 引入模块模块:是一个包含python定义和声明的文件,文件名就是模块名字加上.py后缀,所有的py文件都可以看成是一个 ...

  2. matlab中的linkage和cluster函数

    Linkage: Agglomerative hierarchical cluster tree(凝聚成层次聚类树) 语法: 解释: Z=linkage(x),返回Z,是一个X矩阵中行的分层聚类树(用 ...

  3. abp架构添加实体并使用迁移功能生成表

    参考: https://aspnetboilerplate.com/Pages/Articles/Introduction-With-AspNet-Core-And-Entity-Framework- ...

  4. HTTP security headers 安全头例子

    这是从以下网站测试得到的结果,参考测试项目可以知道哪些安全头应该如何设置. https://observatory.mozilla.org/analyze.html?host=appcanary.co ...

  5. PHP jQuery实现上传图片时预览图片的功能实例

    在PHP项目开发中,有时候经常需要做添加图片的功能.添加图片时,一般需要即时预览上传的图片.下面这个例子就是简单的预览上传图片功能,代码如下(分两部分): 1.HTML代码: <div clas ...

  6. c#委托、泛型、反射的使用情况

    委托:当你传递的参数不是 变量 时,想把一个方法作为参数传递,此时委托就可以做到这点 泛型:当你传递的参数是一个类时,此时用泛型 反射:都说反射是一种耗时的操作,但是却很有用,所以反射他不是拿来滥用的 ...

  7. 【算法】K-Means聚类算法(k-平均或k-均值)

    1.聚类算法和分类算法的区别 a)分类 分类(Categorization or Classification)就是按照某种标准给对象贴标签(label),再根据标签来区分归类. 举例: 假如你有一堆 ...

  8. GIT远程仓库的使用

    查看当前项目有哪些远程仓库 $ git remote bixiaopeng@bixiaopengtekiMacBook-Pro wirelessqa$ git remote origin 查看远程仓库 ...

  9. 网站加入QQ聊天链接

    有时候我们的网站需要加入客服聊天功能,实现方式各不相同同,对于流量不大的网站,可以加入qq聊天的链接,点击链接,会打开本地qq的聊天窗口, 和指定的人会话.实现方式很简单,就是一个<a>标 ...

  10. 利用Filter实现session拦截

    1.在web.xml中配置 <!-- Session监听器 --> <filter> <filter-name>sessionValidateFilter</ ...