这个是一个典型的线程问题。生成者(Productor)生产商品并交给店员(Clerk),消费者(Customer)从店员处购买商品,店员一次性只能购买固定数量的产品,如果生产者试图生成更多的商品,店员会叫生产者暂停一下,如果店里仓库有空位再通知生产者继续生产,如果店中没有商品了,就会告诉消费者等一下,如果店中有商品了就通知消费者来购买。这个场景和我们实际情况也比较贴切,这样就会想可能存在如下问题:

  1. 生产者比消费者快的时,消费者会漏掉部分数据取不到(产品过剩导致浪费,出现滞销)
  2. 消费者比生产者快时,消费者会取到相同的数据(产量不足,供不应求)

在解决这个方法之前先介绍一下线程通信

所谓线程通信可以这样理解:线程与线程之间不是相互独立的个体,它们彼此之间需要相互通信和协作,最典型的例子就是生产者-消费者问题:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权。因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去。因此一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态。然后等待消费者消费了商品,然后消费者通知生产者队列有空间了。同样地,当队列空时,消费者也必须等待,等待生产者通知它队列中有商品了。这种互相通信的过程就是线程间的协作

1.notify/wait

前面的文中通过包括 static synchronized 等手段来解决数据共享的问题,即多个线程主动地读取一个共享数据,通过 同步互斥访问机制保证线程的安全性。等待/通知机制主要由Object类中的wait()、notify() 和 notifyAll()三个方法来实现。

wait():令当前线程挂起并放弃CPU、同步资源,让其他线程可以访问并修改共享资源,而当前现场排队等候以获得再次对资源的访问机会

notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待

notifyAll():唤醒正在排队等待资源的所有线程结束等待。

注意:

  1. 这三个方法均非Thread类中所声明的方法,而是Object类中声明的方法。原因是每个对象都拥有monitor(锁),所以让当前线程等待某个对象的锁,当然应该通过这个对象来操作,而不是用当前线程来操作,因为当前线程可能会等待多个线程的锁,如果通过线程来操作,就非常复杂了。
  2. Java.lang.Object提供的这三个方法只能在synchronized方法或synchronized代码块中使用
package blog;public class TestAccount {public static void main(String[] args) {Account account  = new Account();Account account1  = new Account();//多线程对象User u_weixin = new User(account, 2000);User u_zhifubao = new User(account, 2000);Thread weixin = new Thread(u_weixin,"微信账户");Thread zhifubao = new Thread(u_zhifubao,"支付宝账户");weixin.start();zhifubao.start();}
}class Account{public static int money = 3000;public  void takeMoney5(int m,Account a) {synchronized(a){//表示当前对象的代码被加入了synchronized同步锁,this表示当前对象String name = Thread.currentThread().getName();//如果是微信操作则等待,等支付宝操作完成再给微信操作if (name.equals("微信账户")) {try {a.wait();//当前线程等待进入阻塞状态} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (m > money) {System.out.println(name + "操作,账户金额不足:"+money);}else {System.out.println(name + "操作,账户原有金额:"+money);System.out.println(name + "操作,取款金额:" + m);money = money - m;System.out.println(name + "操作,取款后的余额:" + money);}if (name.equals("支付宝账户")) {try {a.notify();//唤醒当前优先级最高的线程,进入就绪状态} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}class User implements Runnable{Account account;int money;public User(Account account,int money) {this.account = account;this.money = money;}@Overridepublic void run() {account.takeMoney5(money,account);}
}

输出结果如下:

2.生产者/消费者

结合上述介绍的notify/wait机制,下面来实现生产者和消费者

package day15;public class Test3 {public static void main(String[] args) {Clerk c = new Clerk();//消费时不生产,生产时不消费//生产者new Thread(new Runnable() {@Overridepublic void run() {synchronized (c) {while (true) {//无限循环表示无限生产if (c.productNum == 0) {System.out.println("商品数为0,开始生产");while (c.productNum < 5) {c.productNum++;//生产之后,增加商品System.out.println("库存值:"+c.productNum);}System.out.println("产品数为:" + c.productNum +"结束生产");c.notify();//唤醒消费者,让生产者线程等待}else {try {c.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}},"生产者").start();//消费时不生产,生产时不消费//生产者new Thread(new Runnable() {@Overridepublic void run() {synchronized (c) {while (true) {//无限循环表示无限消费if (c.productNum == 5) {System.out.println("商品数为4,开始消费");while (c.productNum  > 0) {c.productNum--;//消费产品,产品减少System.out.println("库存值:"+c.productNum);}System.out.println("产品数为:" + c.productNum +"结束消费");c.notify();//唤醒生产者,让消费者线程等待}else {try {c.wait();//消费者线程等待} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}},"消费者").start();}
}class Clerk{public static int  productNum = 0;}

输出结果如下:

Java多线程(3)—生产者/消费者相关推荐

  1. java多线程之生产者消费者问题

    今天研究了一下Java多线程,根据老师上课讲的和写的,自己写了一下多线程中的经典问题-----生产者消费者经典问题, package producerconsumer; public class Pr ...

  2. Java多线程编程——生产者消费者问题

    一.问题介绍 生产者消费者问题是一个经典的多线程同步问题.该问题描述了两个进程--即所谓的"生产者"和"消费者"--在实际运行时会发生的问题.生产者的主要作用是 ...

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

    文章目录 1.生产者消费者 1.1 生产者和消费者模式概述 1.2 经典案例:生产者和消费者 1.2.1 Object类的等待和唤醒方法 1.2.2 代码实现 1.3 生产者和消费者案例优化 1.3. ...

  4. 【java并发系列】java多线程实现生产者消费者模式

    大家好,我是walker 一个从文科自学转行的程序员~ 爱好编程,偶尔写写编程文章和生活 欢迎关注公众号[I am Walker],回复"电子书",就可以获得200多本编程相关电子 ...

  5. java多线程之~生产者消费者

    文章目录 一.怎样使用多线程 二.生产者消费者 一.怎样使用多线程 一般来讲我们创建多线程的方式有一下几种: 1. 实现Runnable接口 并重写其中的run方法 2. 继承Thread类,重写ru ...

  6. 【Java多线程】生产者消费者问题

    使用管程法 属性定义 缓冲区的容量为10 生产者将生产100个面包 消费者将消费105个面包 思路 生产者不停地生产,生产结果放进缓冲区 消费者不停地消费,从缓冲区中取走产品 当缓冲区为10时,停止生 ...

  7. Java多线程技术~生产者和消费者问题

    Java多线程技术~生产者和消费者问题 本文是上一篇文章的后续,详情点击该连接 线程通信 应用场景:生产者和消费者问题 假设仓库中只能存放一件产品,生产者将生产出来的产品放入仓库,消费者将仓库中产品取 ...

  8. JAVA线程之生产者消费者问题

    复习下JAVA线程基础知识: 1.线程的状态: 创建状态:创建了线程对象,此时线程有了相应的内存空间和其他资源,但处于不可运行状态. 就绪状态:线程对象调用start()方法启动线程,进入就绪状态,此 ...

  9. Linux下实现多线程的生产者消费者问题

    Linux下实现多线程的生产者消费者问题 一.原理的理解 生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制.在同一个线程地址空间内执行的两个线程 ...

  10. Java线程实现生产者—消费者模式

    在这里插入代码片# Java 线程实现生产者-消费者模式 ##思路:实现类似消费者生产者线程之间通讯的功能,每创建一个工人,就让这个工人干活,干一段时间,工人自动消失,然后又去创建一个工人干活: 代码 ...

最新文章

  1. Activity的启动模式总结
  2. python.freelycode.com-Python字节码介绍
  3. android虚拟机的垃圾收集
  4. JAVA入门级教学之(public class和class的区别)
  5. c 自动生成mysql表结构_EntityFrameworkCore 根据实体类自动创建数据库
  6. Js数组排序函数sort()介绍
  7. php+ioncube',IonCube加密PHP程序
  8. python中!ls -r_光学现象的Python实现
  9. python做excel自动化-python操作excel让工作自动化
  10. python中darks_YOLOv4: Darknet 如何于 Ubuntu 编译,及使用 Python 接口
  11. 分布式系统的Raft算法 1
  12. Python编程从入门到实践学习内容包含哪些?
  13. _stdcall,_cdecl区别
  14. 实验一 白盒测试用例设计
  15. Docker最最最最基本的相关操作(不全,还会补充)
  16. PySpark——开启大数据分析师之路
  17. IT行业的人越来越多,工资为啥却不降反升?
  18. 迭代扩展卡尔曼滤波学习
  19. 数据库连接池之自定义连接池(mysql)
  20. 大数据人工智能ai培训师专家讲师叶梓介绍及ChatGPT提纲

热门文章

  1. 任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合(java版),很多人小时候都玩过...
  2. CodeForces1082G Petya and Graph 最小割
  3. 无向图的完美消除序列 判断弦图 ZOJ 1015 Fish net
  4. POJ 1577 Falling Leaves (子母二叉树,给出叶子节点的删除序列,求前序遍历)
  5. hdu_4391,线段树
  6. 使用 Android 实现联网
  7. Bluetooth ATT介绍
  8. STM32 定时器 定时时间的计算
  9. stm32-串口接受不定长数据方法(3种)
  10. C++ Primer 5th笔记(chap 12 动态内存)weak_ptr