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产品 // ...
随机推荐
- 20165225 《Java程序设计》第二周学习总结
20165225<Java程序设计>第二周学习总结 1.视频与课本中的学习: ##### 1.标识符: 字母.下划线.美元符号.数字(不能是true,false,null还有关键字). # ...
- Java如何循环数组并使用Split
场景: 当写方法时遇到1个参数有3个值, 该参数类型为数组. 例如: aaa|bbb|ccc . 而且需要循环打印,这个时候我们就需要用数组循环输出的方法. 一:feature 示例 Wh ...
- 如何解决selenium打开chrome提示chromedriver.exe已停止工作
场景:启动Chrome,打开URL,提示“disconnected: unable to connect to renderer” 解决方法:chromedriver与chrome的对应关系表, 需要 ...
- Feature如何解决参数数量不匹配
问题描述: Feature 写了两个参数,匹配到Steps.Java, 文件只写了两个参数,但是两个参数都加了$ 符号. 而$ 又是结束的意思. 1一:Feature 用例
- knn/kmeans/kmeans++/Mini Batch K-means/Affinity Propagation/Mean Shift/层次聚类/DBSCAN 区别
可以看出来除了KNN以外其他算法都是聚类算法 1.knn/kmeans/kmeans++区别 先给大家贴个简洁明了的图,好几个地方都看到过,我也不知道到底谁是原作者啦,如果侵权麻烦联系我咯~~~~ k ...
- SpringBoot-整合log4j日志记录
新建log4j配置文件 文件名称log4j.properties #log4j.rootLogger=CONSOLE,info,error,DEBUG log4j.rootLogger=info,er ...
- laravel项目ThinkSNS+安装
ThinkSNS+ 是一个使用 Laravel 开发,并且功能繁多且健壮的社交程序.今天我们来跟着ytkah一起来尝鲜一下.首先PHP 版本必须大于 7.1.3,已经下载并安装过 Composer,拥 ...
- 网络传输--UDP
UDP网络编程 一.优缺点 二.套接字socket 三.类型转换 四.UDP发收数据 五.广播和聊天器案例 回到顶部 一.优缺点 UDP : 无连接 (发送端无需确认接收端是否收到), 其主要用途为音 ...
- css中根据不同分辨率设置不同样式
@media screen and (max-width: ) { .tab__content{width: %} }
- 发现Boost官方文档的一处错误(numpy的ndarray)
文档位置:https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/numpy/tutorial/ndarray.html shape在这里 ...