1.生产者消费者模型

public class ProducterConsumerTest{
public static void main(String[] args){
System.out.println("this is a test...");
Message msg=new Message();
Producter pro=new Producter(msg);
Consumer con=new Consumer(msg);
new Thread(pro).start();
new Thread(con).start();
new Thread(con).start();
}
}
class Message {
String title;
String content; public synchronized void set(String title,String content){
//问题1:while 还是 if
while (this.content!=null){
try{
this.wait();
}catch(Exception exc){}
}
//模拟延迟
try{
Thread.sleep(100);
}catch(Exception exc){}
this.title=title;
this.content=content;
System.out.println(Thread.currentThread().getName()+"-生产:"+this.title+this.content);
//问题2 notify 还是notifyAll
super.notify();
}
public synchronized void get(){
//问题1:while 还是 if
while(this.content==null){
try{
this.wait();
}catch(Exception exc){}
}
//模拟延迟
try{
Thread.sleep(100);
}catch(Exception exc){}
System.out.println(Thread.currentThread().getName()+"-消费:"+this.title+this.content);
this.title=null;
this.content=null;
//问题2 notify 还是notifyAll
super.notify();
}
}
class Producter implements Runnable {
Message msg;
public Producter(Message msg){
this.msg=msg;
}
@Override
public void run(){ for(int i=0;i<10;i++){ msg.set("华为"," Meate100");
}
}
}
class Consumer implements Runnable{
Message msg;
public Consumer(Message msg){
this.msg=msg;
}
@Override
public void run(){
for(int i=0;i<5;i++){
msg.get();
}
}
} //运行结果(notifyAll()+while):
this is a test...
生产:华为 Meate100
消费:华为 Meate100
生产:华为 Meate100
消费:华为 Meate100
生产:华为 Meate100
消费:华为 Meate100
生产:华为 Meate100
消费:华为 Meate100
生产:华为 Meate100
消费:华为 Meate100

2.Entry Set(锁池)、Wait Set(等待池)

对于Entry Set:如果线程A已经持有了对象锁,此时有其他线程也想获得该对象锁的话,它只能进入Entry Set,并且线程处于BLOCKED状态。

对于Wait Set:如果线程A调用了wait()方法,那么线程A会释放该对象的锁,进入到Wait Set,并且线程处于WAITING状态。

3.Wait、Notify、NotifyAll 、Entry Set(锁池)、Wait Set(等待池)画图说明

                


                


                

4.衍生出的问题

A.用notify还是notifyAll:

线程1-生产

线程2-消费 -waiting

线程3-消费 -waiting

notify场景分析:

步骤一:线程1生产完成后wait(),执行notify()随机唤醒一个是线程2,判断之后满足条件,进行消费,线程2消费完后wait(),执行notify().

此时三个线程状态是

线程1-waiting

线程2-waiting-执行notify

线程3-waiting

步骤二:这是如果唤醒的是线程3,那么是不满足消费条件的,所以线程3继续wait(),而没有进行唤醒操作

这是问题产生了

线程1-waiting

线程2-waiting

线程3-waiting

死锁、死锁、死锁了...

如果我们用的是notifyAll(),那么步骤一线程2消费完成后,执行notifyAll(),结果是什么呢?

(1)如果是线程1抢到锁,满足条件,进行生产,生产完成后notifyAll()

(2)如果是线程3抢到锁,不满足条件,线程3wait(),释放锁,此时只有线程1是在锁池中,线程1会抢到锁,之后执行(1)

so,notify会导致死锁问题,最好使用notifyAll()

B.wait外层用while还是if:

notifyAll下if运行结果:

这里我没想明白,明明是同步方法为啥子会出现这个问题呢?

或者

就是当线程被wait之后进入等待队列,当被唤醒时,线程是继续往wait下面继续执行还是从synchronized monitor锁的地方再次执行?

答案只有一个:

上边的异常说明了->【wait被唤醒后,会继续往wait之后的代码执行而不是重新从monitor同步块处执行】 (这个结论是从代码运行推断,能力有限,没找到佐证,留待后续补充吧...........)

附上JDK中的说明

C.wait和synchronized绑定使用:

同上图

synchronized wait notify 生产者消费者的更多相关文章

  1. Java多线程之生产者消费者问题&lt;一&gt;:使用synchronized keyword解决生产者消费者问题

    今天看了一片博文,讲Java多线程之线程的协作,当中作者用程序实例说明了生产者和消费者问题,但我及其它读者发现程序多跑几次还是会出现死锁,百度搜了下大都数的样例也都存在bug,经过细致研究发现当中的问 ...

  2. Java学习之线程通信(多线程(synchronized))--生产者消费者

    分析线程经典案例生产者消费者 /** 共享数据 */ class Resource { private String name; private int count=1; private boolea ...

  3. Java多线程(九):生产者消费者模型

    生产者消费者模型 生产者:生产任务的个体: 消费者:消费任务的个体: 缓冲区:是生产者和消费者之间的媒介,对生产者和消费者解耦. 当 缓冲区元素为满,生产者无法生产,消费者继续消费: 缓冲区元素为空, ...

  4. 生产者消费者问题--lock

    # 代码: public class App { public static void main(String[] args) { Depot depot = new Depot(100); Prod ...

  5. 通过生产者消费者模式例子讲解Java基类方法wait、notify、notifyAll

    wait(),notify()和notifyAll()都是Java基类java.lang.Object的方法. 通俗解释wait():在当前线程等待其它线程唤醒.notify(): 唤醒一个线程正在等 ...

  6. 如何在 Java 中正确使用 wait, notify 和 notifyAll – 以生产者消费者模型为例

    wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...

  7. Java 学习笔记 使用synchronized实现生产者消费者模式

    说明 Object.wait()使当前的线程进入到等待状态(进入到等待队列) Object.notifyAll() 唤醒等待中的全部线程 Object.notify() 随机唤醒一个线程 代码 con ...

  8. java使用synchronized与Semaphore解决生产者消费者问题对比

    一.synchronized与信号量Semaphore简介 1.synchronized是java中的关键字,是用来控制线程同步的问题最常用的方法. 2.Semaphore是属于java的一个类,同样 ...

  9. java多线程15 :wait()和notify() 的生产者/消费者模式

    什么是生产者/消费者模型 一种重要的模型,基于等待/通知机制.生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点: ...

随机推荐

  1. HashMap源码__resize

    final Node<K,V>[] resize() { //创建一个Node数组用于存放table中的元素, Node<K,V>[] oldTab = table; //获取 ...

  2. c++ 读取、保存单张图片

    转载:https://www.jb51.net/article/147896.htm 实际上就是以二进制形式打开文件,将数据保存到内存,在以二进制形式输出到指定文件.因此对于有图片的文件,也可以用这种 ...

  3. Eclipse java SE版本解决无法新建web项目问题

    最近工作要涉及web开发,之前下载的java SE (我的是indigo) 版本默认无法新建web项目,也就是找不到Dynamic Web ,在网上看了些解决办法,最终却是解决了问题,说到底就是安装一 ...

  4. Scrapy 下载文件和图片

    我们学习了从网页中爬取信息的方法,这只是爬虫最典型的一种应用,除此之外,下载文件也是实际应用中很常见的一种需求,例如使用爬虫爬取网站中的图片.视频.WORD文档.PDF文件.压缩包等. 1.Files ...

  5. python 网络爬虫(一)

    一.识别网站所用技术 构建网站所使用的技术类型也会对我们如何爬取产生影响.有一个十分有用的工具可以检查网站构建的技术类型---builtwith模块.该模块的安装如下 pip install buil ...

  6. 吴裕雄--天生自然HADOOP操作实验学习笔记:Wor的Count程序的编写

    实验目的 理解mapreduce的工作原理 理解Partitioner的书写方法 理解GroupingComparator的书写方法 实验原理 我们已经学习了hadoop的大部分基础知识,剩下的就是利 ...

  7. 吴裕雄--天生自然HADOOP操作实验学习笔记:安装zookeeper集群

    实验目的 了解zookeeper的概念和原理 学会安装zookeeper集群并验证 掌握zookeeper命令使用 实验原理 1.Zookeeper介绍 ZooKeeper是一个分布式的,开放源码的分 ...

  8. hdu 1086 You can Solve a Geometry Problem too 求n条直线交点的个数

    You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/3 ...

  9. [FBCTF2019]Products Manager

    基于约束的SQL攻击 一.知识点: 1.数据库字符串比较: 在数据库对字符串进行比较时,如果两个字符串的长度不一样,则会将较短的字符串末尾填充空格,使两个字符串的长度一致,比如,字符串A:[Strin ...

  10. 修饰者模式(装饰者模式,Decoration)

    1. 装饰者模式,动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更加有弹性的替代方案. 2.组合和继承的区别 继承.继承是给一个类添加行为的比较有效的途径.通过使用继承,可以使得子类在拥有 ...