Java多线程设计模式(2)生产者与消费者模式
1 Producer-Consumer Pattern
Producer-Consumer Pattern主要就是在生产者与消费者之间建立一个“桥梁参与者”,用来解决生产者线程与消费者线程之间速度的不匹配。
当要从某个线程Produccer参与者将数据传输给其它线程Consumer参与者的时候,此时就可以在中间加一个Channel参与者,在Channel参与者中以某种方式存放接受的数据,再以某方式来获取收到的数据,Channel就可以来缓存两个线程之间传输的数据,在Channel参与者为了保证安全性,也要用Guarded Suspension Pattern模式。
Channel参与者作为一个中间者,当Channel参与者从Producer参与者接收到数据,可以用三种方式将数据按顺序 传递给Consumer参与者。
1 队列,这是一种按照FIFO的方式存储数据,即最先到达的数据最先传输给Consumer参与者。在Java中,可以利用数组形式来存放,每次从数组下标最前端获取数据,而从数组下标最后端来缓存数据。也可以利用LinkedList来存放,每次缓存数据的时候,利用LinkedList.addLast(obj),每次获取数据的时候利用LinkedList.removeFirst();移除并且返回队列的第一个元素。
2 堆栈,这是一种以LIFO的方式存储数据,即最先到达的数据最后传输给Consumer参与者。在Java中,对于堆栈的实现,可以直接使用LinkedList,利用pop()从栈顶弹出一个数据来获取数据,利用push(obj)来向堆栈中缓存一个数据
3 优先级队列,对于缓存的数据设置一些优先级来存储。
生产者与消费者模式,其实就是线程之间的合作关系,同时又包含了互斥关系。所谓的合作就是生产者生成产品,提供消费者消费。所谓的互斥就是生产者和消费者对于中间的缓冲区是互斥访问的。
实例:
几个厨师制作食物,将物品放置在桌子上,但是桌子放置的盘子有限,消费者可以从桌子上获取食物来吃。当桌子上有空位置的时候,厨师就可以继续放置做好的食物,且通知消费者来吃,但是满了就只能一直等待消费者吃了有空的位置。而消费者每次取食物的时候,如果桌子上面有食物,则就取走,并且通知厨师来做食物,如果没有则就等待。
生产者Producer代码:
package whut.producer;
import java.util.Random;
public class MakerThread extends Thread{
private final Table table;
private final Random random;
private static int id=0;
public MakerThread(String name,Table table,long seed)
{
super(name);
this.table=table;
this.random=new Random(seed);
} public void run()
{
try{
while(true)
{
Thread.sleep(random.nextInt(1000));
String cake=" [Cake No."+nextId()+" by "+Thread.currentThread().getName()+"]";
table.put(cake); }
}catch(InterruptedException e)
{
}
}
//为了使得所有实例共享该字段
public static synchronized int nextId()
{
return id++;
}
}
消费者Consumer代码:
package whut.producer;
import java.util.Random;
public class EaterThread extends Thread{
private final Table table;
private final Random random;
public EaterThread(String name,Table table,long seed)
{
super(name);
this.table=table;
this.random=new Random(seed);
}
public void run()
{
try{
while(true)
{
String cake=table.take();
Thread.sleep(random.nextInt(1000));
}
}catch(InterruptedException e)
{
}
}
}
Channel中间缓冲区,关键部分
package whut.producer;
public class Table {
private final String[] cakes;//利用数组来作为缓冲区
private int head;//下一次蛋糕取的位置
private int tail;//下一次蛋糕放置位置
private int count;//桌子上蛋糕的总数
public Table(int count)
{
this.cakes=new String[count];
this.head=0;
this.tail=0;
this.count=0;
} public synchronized void put(String cake)throws InterruptedException
{
System.out.println(Thread.currentThread().getName()+" puts "+cake);
while(count>=cakes.length)
{
System.out.println(Thread.currentThread().getName()+" Begin wait....");
wait();
System.out.println(Thread.currentThread().getName()+" End wait....");
}
cakes[tail]=cake;
tail=(tail+1)%cakes.length;
count++;
notifyAll();
} //取蛋糕
public synchronized String take()throws InterruptedException
{
while(count<=0)
{
System.out.println(Thread.currentThread().getName()+" Begin wait....");
wait();
System.out.println(Thread.currentThread().getName()+" End wait....");
}
String cake=cakes[head];
head=(head+1)%cakes.length;
count--;
notifyAll();
System.out.println(Thread.currentThread().getName()+" gets "+cake);
return cake;
}
}
测试类:
package whut.producer;
public class MainTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Table table=new Table(3);
new MakerThread("MakerThread-1",table,31415).start();
new MakerThread("MakerThread-2",table,92653).start();
new MakerThread("MakerThread-3",table,58979).start(); new EaterThread("EaterThread-1",table,32384).start();
new EaterThread("EaterThread-2",table,32384).start();
new EaterThread("EaterThread-3",table,32384).start();
//可以通过调用interrupt来去中断结束任何线程
}
}
Java多线程设计模式(2)生产者与消费者模式的更多相关文章
- java 线程并发(生产者、消费者模式)
线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...
- Java并发编程(4)--生产者与消费者模式介绍
一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...
- java多线程中的生产者与消费者之等待唤醒机制@Version1.0
一.生产者消费者模式的学生类成员变量生产与消费demo,第一版1.等待唤醒: Object类中提供了三个方法: wait():等待 notify():唤醒单个线程 notify ...
- java多线程中的生产者与消费者之等待唤醒机制@Version2.0
二.生产者消费者模式的学生类成员变量生产与消费demo, @Version2.0 在学生类中添加同步方法:synchronized get()消费者,synchronized set()生产者 最终版 ...
- Java多线程与并发——生产者与消费者应用案例
多线程的开发中有一个最经典的操作案例,就是生产者-消费者,生产者不断生产产品,消费者不断取走产品. package com.vince; /** * 生产者与消费者案例 * @author Admin ...
- java多线程之多生产者-多消费者
多生产者和多消费者是线程通信的经典案例,但是和生产者-消费者相比更为复杂,而且可能会产生程序假死. public class Product { private MyStack myStack; pu ...
- JAVA并发实现五(生产者和消费者模式wait和notify方式实现)
package com.subject01; import java.util.PriorityQueue; /** * 通过wait和notify 实现 * 生产者-消费者模型:当队列满时,生产者需 ...
- JAVA并发实现五(生产者和消费者模式Condition方式实现)
package com.subject01; import java.util.PriorityQueue; import java.util.concurrent.locks.Condition; ...
- Java多线程设计模式(4)线程池模式
前序: Thread-Per-Message Pattern,是一种对于每个命令或请求,都分配一个线程,由这个线程执行工作.它将“委托消息的一端”和“执行消息的一端”用两个不同的线程来实现.该线程模式 ...
随机推荐
- python_ 运算符与分支结构
# 运算符与分支结构 ### 运算符 - 赋值运算符 - 用'='表示,左边只能是变量. - 算术运算符 - +.-.*:加.减.乘 - /:除法运算,结果是浮点数 - //:除法运算,结果是整数 - ...
- (转\整)UE4游戏优化 多人大地型游戏的优化(二)渲染线程的优化
施主分享随缘,评论随心,@author:白袍小道 小道暗语: 1.因为小道这里博客目录没自己整,暂时就用随笔目录结构,所以二级目录那啥就忽略了.标题格式大致都是(原or转) 二级目录 (标题) 2.因 ...
- STL之priority_queue使用简介
优先队列容器也是一种从一端入队,另一端出对的队列.不同于一般队列的是,队列中最大的元素总是位于队首位置,因此,元素的出对并非按照先进先出的要求,将最先入队的元素出对,而是将当前队列中的最大元素出对. ...
- eclipse 运行错误:在类XXX中找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args) 否则 JavaFX 应用程序类必须扩展javafx.application.Application
新建了一个类Hello: 代码: 第一次运行报错: 点击关闭该类的界面时出现: 点击是,然后再次打开,可以正确执行,结果为: 这是为什么....,后来发现了原因:是每次运行或调试前没有自动保存编辑的内 ...
- 【bzoj3585/bzoj3339】mex/Rmq Problem 莫队算法+分块
原文地址:http://www.cnblogs.com/GXZlegend/p/6805283.html 题目描述 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没 ...
- vi - vim的一些遗忘点
1. vi 供分为三种模式:一般模式.编辑模式和命令行模式.i / Esc + :wq :q :q! 使vi在一般模式与编辑模式中来回转换. /word 向下寻找一个名称为word的字符串: ?wor ...
- Spring Boot RabbitMQ 延迟消息实现完整版
概述 曾经去网易面试的时候,面试官问了我一个问题,说 下完订单后,如果用户未支付,需要取消订单,可以怎么做 我当时的回答是,用定时任务扫描DB表即可.面试官不是很满意,提出: 用定时任务无法做到准实时 ...
- [poj] 3304 Segments || 判断线段相交
原题 给出n条线段,判断是否有一条直线与所有线段都有交点 若存在这样一条直线,那么一定存在一条至少过两个线段的端点的直线满足条件. 每次枚举两条线段的两个端点,确定一条直线,判断是否与其他线段都有交点 ...
- unicode 编码在线转换工具--javascript
http://www.cnblogs.com/mq0036/p/4007452.html
- Springboot-plus 安装使用的一些问题
最近在研究一些springboot的框架,然后看到了这个款 springboot plus ,下载下来研究下. 将安装部署的一些问题记录下来了. 第一个,就是部署的时候,我使用的MySQL数据库,导 ...