生产者消费者问题--synchronized
# 代码
public class App {
public static void main(String[] args) {
Depot depot = new Depot(100);
Producer producer = new Producer(depot);
Consumer consumer = new Consumer(depot);
producer.produce(60);
consumer.consume(100);
producer.produce(90);
consumer.consume(40);
}
}
class Depot {
// 仓库最大容量
private int capacity;
// 仓库目前容量
private int size;
public Depot(int capacity) {
this.size = 0;
this.capacity = capacity;
}
public synchronized void produce(int val) {
try {
int surplus = val;
while (surplus > 0) {
while (size >= capacity) {
wait();
}
int incre = (size + surplus) > capacity ? (capacity - size) : surplus;
size += incre;
surplus -= incre;
System.out.printf("%s plan to produce (%d), actually produce (%d), depot size (%d) \n",
Thread.currentThread().getName(), val, incre, size);
notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void consume(int val) {
try {
int surplus = val;
while (surplus > 0) {
while (size <= 0) {
wait();
}
int desc = (size < surplus) ? size : surplus;
size -= desc;
surplus -= desc;
System.out.printf("%s plan to consume (%d), actutally consume (%d), depot size (%d) \n",
Thread.currentThread().getName(), val, desc, size);
notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Producer {
private Depot depot;
public Producer(Depot depot) {
this.depot = depot;
}
public void produce(final int val) {
new Thread() {
public void run() {
depot.produce(val);
}
}.start();
}
}
class Consumer {
private Depot depot;
public Consumer(Depot depot) {
this.depot = depot;
}
public void consume(final int val) {
new Thread() {
public void run() {
depot.consume(val);
}
}.start();
}
}
# 输出:
Thread-0 plan to produce (60), actually produce (60), depot size (60)
Thread-3 plan to consume (40), actutally consume (40), depot size (20)
Thread-2 plan to produce (90), actually produce (80), depot size (100)
Thread-1 plan to consume (100), actutally consume (100), depot size (0)
Thread-2 plan to produce (90), actually produce (10), depot size (10)
# 有四个线程参与了这个过程,两个生产者,两个消费者
# 时隔多月,我们再来考虑一种业务场景,假设要求是,生产的时候的条件是:要么全部生产,要么全部不生产;消费的条件也是:要么全部消费,要么不消费;此时,实现的代码可能如下:
public class Common {
public static void main(String[] args) {
Depot depot = new Depot(100);
Producer producer = new Producer(depot);
Consumer consumer = new Consumer(depot);
for (int i = 0; i < 10; i++) {
producer.produce(50);
}
for (int i = 0; i < 50; i++) {
consumer.consume(10);
}
}
}
class Depot {
// 仓库最大容量
private int capacity;
// 仓库目前容量
private int size;
public Depot(int capacity) {
this.size = 0;
this.capacity = capacity;
}
public synchronized void produce(int val) {
try {
if (size + val > capacity) {
wait();
}
size += val;
System.out.printf("%s produce (%d), depot size (%d) \n", Thread.currentThread().getName(), val, size);
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void consume(int val) {
try {
if (size - val < 0) {
wait();
}
size -= val;
System.out.printf("%s consume (%d), depot size (%d) \n", Thread.currentThread().getName(), val, size);
notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Producer {
private Depot depot;
public Producer(Depot depot) {
this.depot = depot;
}
public void produce(final int val) {
new Thread() {
public void run() {
depot.produce(val);
}
}.start();
}
}
class Consumer {
private Depot depot;
public Consumer(Depot depot) {
this.depot = depot;
}
public void consume(final int val) {
new Thread() {
public void run() {
depot.consume(val);
}
}.start();
}
}
- 运行一下,你会发现仓库中的数量会出现负的情况,如果你改变生产者和消费者的线程数,还有可能出现超过仓库容量的情况,这该怎么解决呢?
- 其实解决方法很简单,把wait()方法的判断语句由if换成while即可;
- 我们来深究原因,以消费者为例,if的情况下,消费线程由wait状态切换到运行状态的时候,不再去判断仓库中的现有的存储量是否满足消费,此时该消费线程有可能由其他的消费线程唤醒,而其他的线程早已经把仓库消费完了,该线程再去消费,仓库自然就变成负的了。而while则不同,判断条件为while时,每次消费者线程被唤醒,均会做一次判断。
- 其实在jdk文档中,对这种情况已经作了强调说明, 如下图所示

! 多读官方文档,多读源码! 手动笑哭。。。
生产者消费者问题--synchronized的更多相关文章
- 【多线程】--生产者消费者模式--synchronized版本
在实现生产者消费者模式之前,我们先了解一下线程的5种状态:被创建.运行.冻结.消亡.阻塞,如下图: 在Jdk1.5发布之前,我们实现生产者消费者模式一般使用synchronized + while循环 ...
- 多线程-生产者消费者(synchronized同步)
正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语 ...
- 【多线程】--生产者消费者模式--Lock版本
在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...
- 生产者-消费者模型的3种Java实现:synchronized,signal/notifyAll及BlockingQueue
我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3555111.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...
- java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比
package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...
- Java 学习笔记 使用synchronized实现生产者消费者模式
说明 Object.wait()使当前的线程进入到等待状态(进入到等待队列) Object.notifyAll() 唤醒等待中的全部线程 Object.notify() 随机唤醒一个线程 代码 con ...
- java使用synchronized与Semaphore解决生产者消费者问题对比
一.synchronized与信号量Semaphore简介 1.synchronized是java中的关键字,是用来控制线程同步的问题最常用的方法. 2.Semaphore是属于java的一个类,同样 ...
- Java多线程-同步:synchronized 和线程通信:生产者消费者模式
大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...
- Java学习之线程通信(多线程(synchronized))--生产者消费者
分析线程经典案例生产者消费者 /** 共享数据 */ class Resource { private String name; private int count=1; private boolea ...
随机推荐
- C# Timespan Tostring 时分秒格式
timeSpan.ToString(@"hh\:mm\:ss");
- Day6 && Day7图论
并查集 A - How Many Answers Are Wrong 题意:已知区间[1,n],给出m组数据,即[l,r]区间内数据之和为s,求错误数据的数量. 拿到这道题,真的没思路,知道用并查集, ...
- 利用netsh命令设置IP地址/DNS服务器地址
一.设置IP地址 1. 自动获取IP地址: netsh interface ip set address [name=]"本地连接" [source=]dhcp 2. 手动设置IP ...
- 【Linux】常用基础命令
修改时间 date -s 月/日/年 例如:date -s 07/31/2019 date -s 时:分:秒 例如:date -s 23:56:50 hwclock -w 将时间写到bois,防止重启 ...
- 看我如何通过邮箱获取IP定位-复现
环境准备:一台部署了phpstudy 的vps 脚本内容:get_ip.php 该脚本可以生成一个十分隐蔽的图片,并获取客户端的一些敏感信息. 代码内容如下: <?php //show_sour ...
- Windows下的开发辅助神器——Chocolate Package Manager
Windows下的开发辅助神器——Chocolate Package Manager:https://juejin.im/post/5c6cb3acf265da2dc4537235 Windows上的 ...
- ufile的硬盘
参考: https://docs.ucloud.cn/compute/uhost/introduction/disk UFS: https://docs.ucloud.cn/storage_cdn/u ...
- celery 调用scrapy
我的环境: celery 3.1.25 python 3.6.9 window10 celery tasks 代码如下,其中 QuotesSpider 是我的scrapy项目爬虫类名称 from ce ...
- # 深圳杯D题爬取电视收视率排行榜
目录 深圳杯D题爬取电视收视率排行榜 站点分析 代码实现 深圳杯D题爬取电视收视率排行榜 站点分析 http://www.tvtv.hk/archives/category/tv 每天的排行版通过静态 ...
- 集成学习-Boosting 模型深度串讲
首先强调一下,这篇文章适合有很好的基础的人 梯度下降 这里不系统讲,只介绍相关的点,便于理解后文 先放一个很早以前写的 梯度下降 实现 logistic regression 的代码 def tidu ...