对这个问题更深一点理解是,每一个线程都在竞争这个类的实例的monitor对象。

  java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronized methods )被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。

  任何时刻,对一个指定object对象的某同步方法只能由一个线程来调用。java对象的monitor是跟随object实例来使用的,而不是跟随程序代码。两个线程可以同时执行相同的同步方法,比如:一个类的同步方法是xMethod(),有a,b两个对象实例,一个线程执行a.xMethod(),另一个线程执行b.xMethod(). 互不冲突。下面是单生产者单消费者的实例

 /*
* 生产者消费者
* 分类:
* 单生产者单消费者
* 多生产者的消费者
*
*
* 单生产者单消费者:
* 两个线程:生产线程,消费线程
* 两个任务:生产任务,消费任务
* 一份数据
*/
public class Demo4 {
public static void main(String[] args) {
//1.准备数据
Product product = new Product();
//2.创建生产消费任务
Producer producer = new Producer(product);
Consumer consumer = new Consumer(product);
//3.创建生产消费线程
Thread thread1 = new Thread(producer);
Thread thread2 = new Thread(consumer);
//4.开启线程
thread1.start();
thread2.start();
}
} //数据类
class Product{
String name;
double price;
int count; //标识
boolean flag; //准备生产
public synchronized void setProduce(String name,double price) {
if (flag == true) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} this.name = name;
this.price = price; System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); count++; flag = !flag; //唤醒消费线程
notify();
}
//准备消费
public synchronized void consume() {
if (flag == false) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} System.out.println(Thread.currentThread().getName()+" 消费了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); flag = !flag; //唤醒生产线程
notify();
}
}
//生产任务
class Producer implements Runnable{
Product product; public Producer(Product product) {
super();
this.product = product;
} public void run() {
while (true) {
product.setProduce("bingbing", 10);
}
}
}
//消费任务 class Consumer implements Runnable{
Product product; public Consumer(Product product) {
super();
this.product = product;
} public void run() {
while (true) {
product.consume();
}
}
}

生产者消

 多生产者多消费者:
 * 两个生产线程,两个消费线程
 * 两个任务:生产任务,消费任务
 * 一份数据
 *
 * 生产任务与消费任务共用一个数据--产品类
 *
 * 要求:最终也要实现一次生产一次消费
 *
 *错误描述:当有两个生产线程,两个消费线程同时存在的时候,有可能出现生产一次,消费多次或者生产多次消费一次的情况.
 *原因:当线程被重新唤醒之后,没有判断标记,直接执行了下面的代码
 *
 *解决办法:将标记处的if改成while
 *
 *问题描述:继续运行程序,会出现死锁的情况(4个线程同时处于等待状态)
 *原因:唤醒的是本方的线程,最后导致所有的线程都处于等待状态.
 *
 *解决办法:将notify改成notifyAll.保证将对方的线程唤醒
 *
 *死锁:出现的情况有两种
 *1.所有的线程处于等待状态
 *2.锁之间进行嵌套调用
 *
 */

public class Demo5 {
public static void main(String[] args) {
//1.准备数据
Product1 product = new Product1();
//2.创建生产消费任务
Producer1 producer = new Producer1(product);
Consumer1 consumer = new Consumer1(product);
//3.创建生产消费线程
Thread thread0 = new Thread(producer);
Thread thread1 = new Thread(producer);
Thread thread2 = new Thread(consumer);
Thread thread3 = new Thread(consumer);
//4.开启线程
thread0.start();
thread1.start();
thread2.start();
thread3.start();
}
} //数据类
class Product1{
String name;
double price;
int count; //标识
boolean flag; //准备生产
public synchronized void setProduce(String name,double price) {
while (flag == true) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} this.name = name;
this.price = price; System.out.println(Thread.currentThread().getName()+" 生产了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); count++; flag = !flag; //唤醒消费线程
//notify();
notifyAll();
}
//准备消费
public synchronized void consume() {
while (flag == false) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} System.out.println(Thread.currentThread().getName()+" 消费了:"+name+" 产品的数量:"+count+" 产品的价格:"+price); flag = !flag; //唤醒生产线程
//notify();
notifyAll();
}
}
//生产任务
class Producer1 implements Runnable{
Product1 product; public Producer1(Product1 product) {
super();
this.product = product;
} public void run() {
while (true) {
product.setProduce("bingbing", 10);
}
}
}
//消费任务 class Consumer1 implements Runnable{
Product1 product; public Consumer1(Product1 product) {
super();
this.product = product;
} public void run() {
while (true) {
product.consume();
}
}
}

Java 多线程同步生产者消费者问题-monitor的更多相关文章

  1. Java多线程同步——生产者消费者问题

    这是马士兵老师的Java视频教程里的一个生产者消费者问题的模型 public class ProduceConsumer{ public static void main(String[] args) ...

  2. java多线程解决生产者消费者问题

    import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...

  3. java多线程模拟生产者消费者问题,公司面试常常问的题。。。

    package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 // ...

  4. Java多线程_生产者消费者模式2

    在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...

  5. JAVA多线程之生产者 消费者模式 妈妈做面包案例

    创建四个类 1.面包类 锅里只可以放10个面包 ---装面包的容器2.厨房 kitchen 生产面包 和消费面包  最多生产100个面包3.生产者4消费者5.测试类 多线程经典案例 import ja ...

  6. 【多线程】java多线程实现生产者消费者模式

    思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...

  7. Java多线程之生产者消费者问题<一>:使用synchronized keyword解决生产者消费者问题

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

  8. Java多线程实现生产者消费者延伸问题

    在操作系统中有一类问题被称为生产者消费者问题:意为,有数个生产者生产产品,有数个消费者消费产品,他们共享一定数量的缓存. 这里用java多线程编程,实现生产者消费者问题的一种延伸,橘子苹果问题. 题目 ...

  9. Java多线程-----实现生产者消费者模式的几种方式

       1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...

随机推荐

  1. 03.Jquery Mobile中的按钮

    一. 基础按钮 1.设置链接的data-role,使其变成按钮. <a href="index.html" data-role="button">L ...

  2. 【aspnetcore】添加自定义json配置文件

    打开program.cs文件,修改CreateWebHostBuilder方法: public static IWebHostBuilder CreateWebHostBuilder(string[] ...

  3. shell 获得调用的python脚本的print值和错误log

    1. shell 获得调用的python脚本的print值 python test.py > out.log 2.shell 获得调用的python脚本的错误log python test.py ...

  4. postgresql修改数据库名

    alter database abc rename to cba;

  5. C#里边的控件缩写大全(比较规范)

    标准控件1 btn Button 2 chk CheckBox 3 ckl CheckedListBox 4 cmb ComboBox 5 dtp DateTimePicker 6 lbl Label ...

  6. 洛谷P3928 SAC E#1 - 一道简单题 Sequence2

    提交地址 题目背景 小强和阿米巴是好朋友. 题目描述 小强喜欢数列.有一天,他心血来潮,写下了三个长度均为n的数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种,波动数列. 阿米巴把他的喜好告诉了小强. ...

  7. JAVA基础之项目分包

    个人理解: 项目分层分包适合多人开发合作的,最好一个界面设置一个view,同时注释一定设置好,按照顺序:从前向后进行传递参数,从后向前进行传递返回值来进行判断是否真正的执行了sql语句(可以不返回), ...

  8. 从wireshark数据中分析rtmp协议,并提取出H264视频流

    我写的小工具 rtmp_parse.exe 使用用法如先介绍下: -sps  [文件路径] 解析 sps 数据 文件当中的内容就是纯方本的hexstring: 如 42 E0 33 8D 68 05 ...

  9. 【虚拟机-磁盘管理】理解及快速测定 Azure 虚拟机的磁盘性能

    随着越来越多的用户将生产系统迁移到 Azure 平台的虚拟机服务中,Azure 虚拟机的性能愈发被关注.传统的数据中心中,我们通常使用 CPU,内存,存储和网络的性能来衡量生产压力.特别是对于 IO ...

  10. JavaScript 的 parseInt 取整

    http://www.neoease.com/javascript-get-integer-via-parseint/ JavaScript 是弱类型语言, 为了保证数值的有效性, 在处理数值的时候, ...