Java 多线程同步生产者消费者问题-monitor
对这个问题更深一点理解是,每一个线程都在竞争这个类的实例的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的更多相关文章
- Java多线程同步——生产者消费者问题
这是马士兵老师的Java视频教程里的一个生产者消费者问题的模型 public class ProduceConsumer{ public static void main(String[] args) ...
- java多线程解决生产者消费者问题
import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...
- java多线程模拟生产者消费者问题,公司面试常常问的题。。。
package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 // ...
- Java多线程_生产者消费者模式2
在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...
- JAVA多线程之生产者 消费者模式 妈妈做面包案例
创建四个类 1.面包类 锅里只可以放10个面包 ---装面包的容器2.厨房 kitchen 生产面包 和消费面包 最多生产100个面包3.生产者4消费者5.测试类 多线程经典案例 import ja ...
- 【多线程】java多线程实现生产者消费者模式
思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...
- Java多线程之生产者消费者问题<一>:使用synchronized keyword解决生产者消费者问题
今天看了一片博文,讲Java多线程之线程的协作,当中作者用程序实例说明了生产者和消费者问题,但我及其它读者发现程序多跑几次还是会出现死锁,百度搜了下大都数的样例也都存在bug,经过细致研究发现当中的问 ...
- Java多线程实现生产者消费者延伸问题
在操作系统中有一类问题被称为生产者消费者问题:意为,有数个生产者生产产品,有数个消费者消费产品,他们共享一定数量的缓存. 这里用java多线程编程,实现生产者消费者问题的一种延伸,橘子苹果问题. 题目 ...
- Java多线程-----实现生产者消费者模式的几种方式
1 生产者消费者模式概述 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题.生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理 ...
随机推荐
- JS高级学习历程-8
2 构造函数和普通函数的区别 两者本身没有实质区别,具体看使用 new 函数(); -------->构造函数 函数(); ---------> 普通函数 <!D ...
- CodeForces - 608A-Saitama Destroys Hotel(模拟)
Saitama accidentally destroyed a hotel again. To repay the hotel company, Genos has volunteered to o ...
- php:比较两个txt文件,格式如下,分别取出a.txt有的b.txt没有的,b.txt有的a.txt没有的及两个都有的
<?php /*比较两个txt文件,格式如下,分别取出a.txt有的b.txt没有的,b.txt有的a.txt没有的及两个都有的 * a.txt: * A * B * C * D * b.txt ...
- NET Core准备:使用Hyper-V安装Ubuntu Server 16.10
NET Core准备:使用Hyper-V安装Ubuntu Server 16.10 概述 Hyper-V是微软的一款虚拟化产品,和VMWare一样采用的hypervisor技术.它已经被内嵌到Win1 ...
- 解决win10下python3和python2共存pip的问题
经过在查阅网友的各种经验,发现仍然解决不了问题,python2和python3在win10下的安装就不再演示了,直接在python的官网下载就好,我机器上使用的是python2.7.15和python ...
- JS中实现JSON对象和JSON字符串之间的相互转换
对于主流的浏览器(比如:firefox,chrome,opera,safari,ie8+),浏览器自己提供了JSON对象,其中的parse和stringify方法实现了JSON对象和JSON字符串之间 ...
- 8.对于.NET的初步理解和介绍
好久没写博客了,最近心情比较low,不知道为什么.很流行的一个问题叫做:如果你明天就挂了,那么你最后悔的事情将会是什么.我想了两个月,答案是不知道,无所谓.这样不好,那这个问题先放一边吧,我们开始这一 ...
- sql常用操作(一)
sql(structured query language,结构化查询语言)语言:和数据库交互的语言,进行数据库管理的语言. 1.1 sql语句的作用:说白了就是增删改查 管理数据库 管理表 管理数据 ...
- RSA_new()初始化和RSA_free()释放RSA结构体后依然会有内存泄漏(转)
在使用OpenSSL的RSA加解密的时候,发现RSA_new()初始化和RSA_free()释放RSA结构体后依然会有内存泄漏.网上Baidu.Google之,发现这个相关信息很少(至少中文搜索结果是 ...
- PHP的加解密:如何安装ioncube扩展?
一.下载loader-wizard.php(支持php5.3.php5.4.php5.5.php5.6版本) ioncube提供了一个安装的向导程序,可以非常方便的帮助检测php的运行环境,自动给出提 ...