Java多线程-----实现生产者消费者模式的几种方式
1 生产者消费者模式概述
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,
直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,
才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式
2 实现生产者消费者模式
产品类
package com.thread.pc.blockingqueue; import java.util.UUID; /**
* 产品类
*
* @author yyx 2018年12月22日
*/
public class Product {
private UUID proCode; // 产品唯一编码 public Product(UUID proCode) {
super();
this.proCode = proCode;
} public UUID getProCode() {
return proCode;
} public void setProCode(UUID proCode) {
this.proCode = proCode;
} }
生产者
package com.thread.pc.lockcondition; /**
* 生产者
* @author yyx 2019年1月5日
*/
public class Producer implements Runnable {
private Warehouse warehouse; public Producer(Warehouse warehouse) {
super();
this.warehouse = warehouse;
} @Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
warehouse.addProduct();
}
} }
消费者
package com.thread.pc.lockcondition; /**
* 消费者
*
* @author yyx 2019年1月5日
*/
public class Consumer implements Runnable {
private Warehouse warehouse; public Consumer(Warehouse warehouse) {
super();
this.warehouse = warehouse;
} @Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
warehouse.removeProduct();
}
}
}
2.1 使用lock、condition和await、singalAll
仓库类
package com.thread.pc.lockcondition; import java.util.List;
import java.util.UUID;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; /**
* 仓库类
*
* @author yyx 2019年1月5日
*/
public class Warehouse {
private final int MAX_SIZE = 5;
private List<Product> listProduct;
private Lock lock;
private Condition conditionProducer;
private Condition conditionConsumer; public Warehouse(List<Product> listProduct, Lock lock, Condition conditionProducer, Condition conditionConsumer) {
super();
this.listProduct = listProduct;
this.lock = lock;
this.conditionProducer = conditionProducer;
this.conditionConsumer = conditionConsumer;
} public void addProduct() {
lock.lock();
try {
String currentName = Thread.currentThread().getName();
while (listProduct.size() >= MAX_SIZE) { // 为了避免虚假唤醒,应该总是使用在循环中
try {
System.out.println("产品列表已满,不再生产!" + currentName + "进入等待");
conditionProducer.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = new Product(UUID.randomUUID());
System.out.println(currentName + "生产了一个产品,它的编号是:" + product.getProCode().toString());
listProduct.add(product);
conditionConsumer.signalAll();
} finally {
lock.unlock();
}
} public void removeProduct() {
lock.lock();
try {
String currentName = Thread.currentThread().getName();
while (listProduct.size() <= 0) {
try {
System.out.println("产品列表不足,不再消费!" + currentName + "进入等待");
conditionConsumer.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = listProduct.get(0);
System.out.println(currentName + "消费了一个产品,它的编号是:" + product.getProCode().toString());
listProduct.remove(0);
conditionProducer.signalAll();
} finally {
lock.unlock();
}
}
}
测试类
package com.thread.pc.lockcondition; import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 测试类
* @author 2018年12月22日
*/
public class TestModel {
public static void main(String[] args) {
List<Product> listProduct=new ArrayList<Product>();
Lock lock = new ReentrantLock();
Condition conditionProducer = lock.newCondition();
Condition conditionConsumer = lock.newCondition(); Warehouse warehouse = new Warehouse(listProduct,lock, conditionProducer,conditionConsumer);
Producer producer = new Producer(warehouse);
Consumer consumer = new Consumer(warehouse); new Thread(producer,"生产者A").start();
new Thread(producer,"生产者B").start();
new Thread(consumer,"消费者C").start();
new Thread(consumer,"消费者D").start();
}
}
2.2 使用synchronized修饰代码块
仓库类
package com.thread.pc.synchronizedcodeblock; import java.util.List;
import java.util.UUID; /**
* 仓库类
*
* @author yyx 2019年1月5日
*/
public class Warehouse {
private final int MAX_SIZE = 10; // 最大数量
private List<Product> listProduct; public Warehouse(List<Product> listProduct) {
super();
this.listProduct = listProduct;
} /**
* 生产产品
*/
public void addProduct() {
synchronized (listProduct) {
String currentName = Thread.currentThread().getName();
while (listProduct.size() >= MAX_SIZE) { // 为了避免虚假唤醒,应该总是使用在循环中
try {
System.out.println("产品列表已满,不再生产!" + currentName + "进入等待");
listProduct.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = new Product(UUID.randomUUID());
System.out.println(currentName + "生产了一个产品,它的编号是:" + product.getProCode().toString());
listProduct.add(product);
listProduct.notifyAll();
}
} /**
* 消费产品
*/
public void removeProduct() {
synchronized (listProduct) {
String currentName = Thread.currentThread().getName();
while (listProduct.size() <= 0) {
try {
System.out.println("产品列表不足,不再消费!" + currentName + "进入等待");
listProduct.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = listProduct.get(0);
System.out.println(currentName + "消费了一个产品,它的编号是:" + product.getProCode().toString());
listProduct.remove(0);
listProduct.notifyAll();
}
}
}
测试类
package com.thread.pc.synchronizedcodeblock; import java.util.ArrayList;
import java.util.List; /**
* 测试类
* @author yyx
* 2019年1月5日
*/
public class TestModel {
public static void main(String[] args) {
List<Product> listProduct = new ArrayList<Product>(); Warehouse warehouse = new Warehouse(listProduct);
Producer producer = new Producer(warehouse);
Consumer consumer = new Consumer(warehouse); new Thread(producer,"生产者A").start();
new Thread(producer,"生产者B").start();
new Thread(consumer,"消费者C").start();
new Thread(consumer,"消费者D").start();
}
}
2.3 使用synchronized修饰方法
仓库类
package com.thread.pc.synchronizedmethod; import java.util.List;
import java.util.UUID; /**
* 仓库类
*
* @author yyx 2019年1月5日
*/
public class Warehouse {
private final int MAX_SIZE = 10;
private List<Product> listProduct; public Warehouse(List<Product> listProduct) {
super();
this.listProduct = listProduct;
} /**
* 生产产品
*/
public synchronized void addProduct() {
String currentName = Thread.currentThread().getName();
while (listProduct.size() >= MAX_SIZE) {
try {
System.out.println("产品列表已满,不再生产!" + currentName + "进入等待");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = new Product(UUID.randomUUID());
System.out.println(currentName + "生产了一个产品,它的编号是:" + product.getProCode().toString());
listProduct.add(product);
notifyAll();
} /**
* 消费产品
*/
public synchronized void removeProduct() {
String currentName = Thread.currentThread().getName();
while (listProduct.size() <= 0) {
try {
System.out.println("产品列表不足,不再消费!" + currentName + "进入等待");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = listProduct.get(0);
System.out.println(currentName + "消费了一个产品,它的编号是:" + product.getProCode().toString());
listProduct.remove(0);
notifyAll();
}
}
测试类
package com.thread.pc.synchronizedmethod; import java.util.ArrayList;
import java.util.List; /**
* 测试类
*
* @author yyx 2019年1月5日
*/
public class TestModel {
public static void main(String[] args) {
List<Product> listProduct = new ArrayList<Product>(); Warehouse warehouse = new Warehouse(listProduct);
Producer producer = new Producer(warehouse);
Consumer consumer = new Consumer(warehouse); new Thread(producer, "生产者A").start();
new Thread(producer, "生产者B").start();
new Thread(consumer, "消费者C").start();
new Thread(consumer, "消费者D").start();
}
}
2.4 使用BlockingQueue
仓库类
package com.thread.pc.blockingqueue; import java.util.UUID;
import java.util.concurrent.BlockingQueue;
/**
* 仓库
* @author yyx 2018年12月22日
*/
public class Warehouse {
private final int MAX_SIZE = 10;
private BlockingQueue<Product> blockingQueue; public Warehouse(BlockingQueue<Product> blockingQueue) {
super();
this.blockingQueue = blockingQueue;
} public void addProduct() {
String currentName = Thread.currentThread().getName();
if (blockingQueue.size() >= MAX_SIZE) {
System.out.println("产品列表已满,不再生产!" + currentName + "进入等待");
} else {
Product product = new Product(UUID.randomUUID());
System.out.println(currentName + "生产了一个产品,它的编号是:" + product.getProCode().toString());
try {
blockingQueue.put(product);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public void removeProduct() {
String currentName = Thread.currentThread().getName();
if (blockingQueue.size() <= 0) {
System.out.println("产品列表不足,不再消费!" + currentName + "进入等待");
} else {
try {
Product product = blockingQueue.take();
System.out.println(currentName + "消费了一个产品,它的编号是:" + product.getProCode().toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试类
package com.thread.pc.blockingqueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* 测试类
* @author yyx 2018年12月22日
*/
public class TestModel {
public static void main(String[] args) {
BlockingQueue<Product> blockingQueue = new LinkedBlockingQueue<>(10); Warehouse warehouse = new Warehouse(blockingQueue);
Producer producer = new Producer(warehouse);
Consumer consumer = new Consumer(warehouse); new Thread(producer).start();
new Thread(producer).start();
new Thread(consumer).start();
}
}
Java多线程-----实现生产者消费者模式的几种方式的更多相关文章
- Java多线程_生产者消费者模式2
在我的上一条博客中,已经介绍到了多线程的经典案列——生产者消费者模式,但是在上篇中用的是传统的麻烦的非阻塞队列实现的.在这篇博客中我将介绍另一种方式就是:用阻塞队列完成生产者消费者模式,可以使用多种阻 ...
- 【多线程】java多线程实现生产者消费者模式
思考问题: 1.为什么用wait()+notify()实现生产者消费者模式? wait()方法可以暂停线程,并释放对象锁 notify()方法可以唤醒需要该对象锁的其他线程,并在执行完后续步骤,到了s ...
- JAVA多线程之生产者 消费者模式 妈妈做面包案例
创建四个类 1.面包类 锅里只可以放10个面包 ---装面包的容器2.厨房 kitchen 生产面包 和消费面包 最多生产100个面包3.生产者4消费者5.测试类 多线程经典案例 import ja ...
- Java多线程编程——生产者-消费者模式(1)
生产者-消费者模式在生活中非常常见.就拿我们去餐馆吃饭为例.我们会遇到以下两种情况: 1.厨师-客人 如下图所示,生产者.消费者直接进行交互. 生产者生产出产品后,通知消费者:消费者消费后,通知生产者 ...
- Java多线程_生产者消费者模式1
生产者消费者模型 具体来讲,就是在一个系统中,存在生产者和消费者两种角色,他们通过内存缓冲区进行通信,生产者生产消费者需要的资料,消费者把资料做成产品.生产消费者模式如下图.(图片来自网络 ...
- java多线程解决生产者消费者问题
import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...
- 【多线程】--生产者消费者模式--Lock版本
在JDK1.5发布后,提供了Synchronized的更优解决方案:Lock 和 Condition 我们使用这些新知识,来改进例子:[多线程]--生产者消费者模式--Synchronized版本 改 ...
- Java设计模式之生产者消费者模式
Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...
- java多线程模拟生产者消费者问题,公司面试常常问的题。。。
package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 // ...
随机推荐
- linux下tomcat启动没有日志,没有进程,没有报错,没有监听端口
可以试试运行catalina.sh run,这个命令会让tomcat在终端打印日志.
- Java如何写Common直接调用
一:新建Class类,命名为:Common 1. 写public static 公共的静态方法: 2. 直接用 Common.方法名 就可以直接调用. 例如:写一个获取当前星期的方法. /** ...
- 洛谷P1966 火柴排队 贪心+离散化+逆序对(待补充QAQ
正解: 贪心+离散化+逆序对 解题报告: 链接在这儿呢quq 这题其实主要难在想方法吧我觉得?学长提点了下说用贪心之后就大概明白了,感觉没有很难 但是离散化这里还是挺有趣的,因为并不是能很熟练地掌握离 ...
- 第5章 实现windows程序的数据绑定
1:连接式: command 对象负责对数据库的执行命令 DataReader 对象负责从数据源中读取数据 connection 对象负责链接数据库 断开式: 数据集的Dataset存放在独立的数据源 ...
- CSS学习(二)
<!DOCTYPE html> <html> <head> <meta charset="{CHARSET}"> <title ...
- Filter & Listener
一 监听器的概述 监听器就是一个实现了特定接口的Java类,用于监听另一个Java类的方法调用或属性的改变.当被监听对象发生上述事件后,监听器某个方法将会立即被执行. 即用来监听其他对象的变化,主要应 ...
- SQL Server2008及以上 表分区操作详解
SQL Server 表分区之水平表分区 转自:https://www.cnblogs.com/Brambling/p/6766482.html 什么是表分区? 表分区分为水平表分区和垂直表分区,水 ...
- 前端 HTML 常用标签 head标签相关内容 title标签 网页的标题信息
title标签 <title>标签:在<title>和</title>标签之间的文字内容是网页的标题信息,它会显示在浏览器标签页的标题栏中. 可以把它看成是一个网页 ...
- linux 修改文件内容 vi命令
vi编辑器是所有Unix及Linux系统下标准的编辑器,介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相同的,因此您可以在其他任何介绍vi的地方进一步了解它 ...
- C 语言循环结构
25.有如下程序 main() { int i,sum; for(i=1;i<=3;sum++) sum+=i; printf("%d\n",sum); } 该程序的执行 ...