# 代码

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的更多相关文章

  1. 【多线程】--生产者消费者模式--synchronized版本

    在实现生产者消费者模式之前,我们先了解一下线程的5种状态:被创建.运行.冻结.消亡.阻塞,如下图: 在Jdk1.5发布之前,我们实现生产者消费者模式一般使用synchronized + while循环 ...

  2. 多线程-生产者消费者(synchronized同步)

    正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语 ...

  3. 【多线程】--生产者消费者模式--Lock版本

    在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...

  4. 生产者-消费者模型的3种Java实现:synchronized,signal/notifyAll及BlockingQueue

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3555111.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  5. java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比

    package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...

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

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

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

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

  8. Java多线程-同步:synchronized 和线程通信:生产者消费者模式

    大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...

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

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

随机推荐

  1. Python基于回溯法解决01背包问题实例

    Python基于回溯法解决01背包问题实例 这篇文章主要介绍了Python基于回溯法解决01背包问题,结合实例形式分析了Python回溯法采用深度优先策略搜索解决01背包问题的相关操作技巧,需要的朋友 ...

  2. Document、HTMLDocument关系的探究

    首先贴上代码: console.log(Object.getPrototypeOf(document)); console.log(Object.getPrototypeOf(Object.getPr ...

  3. etcd 使用: golang 例子

    一:连接到 etcd package main import ( "fmt" "go.etcd.io/etcd/clientv3" "time&quo ...

  4. office web apps安装部署,配置https,负载均衡(五)配置服务器场

    前提条件:您已经完成了域控制器的配置,拥有域账号,并且已经安装了OWA启动所需要的必要软件: 具体步骤可以参考: office web apps安装部署,配置https,负载均衡(一)背景介绍 off ...

  5. java安全停止线程

    Thread.stop()是一个被废弃的方法,不被推荐使用的原因是stop方法太过于暴力,强行把执行到一半的线程终止,并且会立即释放这个线程所有的锁.会破坏了线程中引用对象的一致性. 使用判断标志位的 ...

  6. 【AMAD】django-rules -- 强大的Django鉴权库,不需要数据库

    动机 简介 个人评分 动机 Django默认的权限原子级别是model级.但是一些时候我们像针对model每条数据库记录都进行权限空,也就是对象级权限控制. 简介 django-rules是一个Dja ...

  7. 【MapReduce】二、MapReduce编程模型

      通过前面的实例,可以基本了解MapReduce对于少量输入数据是如何工作的,但是MapReduce主要用于面向大规模数据集的并行计算.所以,还需要重点了解MapReduce的并行编程模型和运行机制 ...

  8. 【Linux开发】内核模块简介

    一. 摘要 这篇文章主要介绍了Linux内核模块的相关概念,以及简单的模块开发过程.主要从模块开发中的常用指令.内核模块程序的结构.模块使用计数以及模块的编译等角度对内核模块进行介绍.在Linux系统 ...

  9. 简单的利用nginx部署前端项目

    网上有很多教程写的一大堆东西,新手可能会有点看不懂,现在我写这篇文章是为了更好的帮助新手,如何将自己的前端项目部署到自己的服务器上. 首先我们必须要有一台自己的ubuntu服务器,如果没有可以去阿里云 ...

  10. python 爬虫 基于requests模块的get请求

    需求:爬取搜狗首页的页面数据 import requests # 1.指定url url = 'https://www.sogou.com/' # 2.发起get请求:get方法会返回请求成功的响应对 ...