生产者与消费者模式简单介绍:
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来
以示例来说明问题:
以下程序参考至: http://www.iteye.com/topic/256991
首先是产品类:
package consumerandproducter;
/**
* 单纯的产品类
* @author google
*
*/
public class Product {
private int productId=0;
public Product(int id){
this.productId=id;
}
public int getProductId() {
return productId;
}
public String toString(){
return "product "+productId;
}
}
再是仓库(缓冲区):
package consumerandproducter;
/**
* 模拟缓冲区,以栈为数据结构,先进后出
* @author google
*
*/
public class StoreHouse {
private int base=0;
private int top=0;
private Product[] products=new Product[10];
/**
* 入栈
* @param product
*/
public synchronized void push (Product product) {
while(top==products.length){
//当前的线程已经放弃对资源的占有,唤醒已经被wait的线程,唤醒的线程由JVM决定,不按优先级确定
notify();
try {
System.out.println("仓库已满,正在等待消费……");
wait();//此线程处于等待状态
} catch (Exception e) {
e.printStackTrace();
}
}
products[top]=product;
top++;
}
/**
* 出栈
* @return
*/
public synchronized Product pop(){
Product product=null;
while(top==base){
notify();
try {
System.out.println("仓库已空,正在等待生产……");
wait();
} catch (Exception e) {
e.printStackTrace();
}
}
top--;
product=products[top];
products[top]=null;
return product;
}
}
接着是消费者:
package consumerandproducter;
public class Consumer implements Runnable {
private String consumerName;
//保留有缓冲区对象的引用,以便消费产品
private StoreHouse storeHouse;
public Consumer(String consumerName, StoreHouse storeHouse) {
this.consumerName = consumerName;
this.storeHouse = storeHouse;
}
public void run() {
while(true){
System.out.println("消费者"+consumerName+"已经消费"+storeHouse.pop());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public String getConsumerName() {
return consumerName;
}
public void setConsumerName(String consumerName) {
this.consumerName = consumerName;
}
}
然后是生产者:
package consumerandproducter;
/**
* 生产者类
* @author google
*
*/
public class Producter implements Runnable {
private String producterName;
// 保留有缓冲区对象的引用,以便将生产的产品放入缓冲区
private StoreHouse storeHouse;
public Producter(String producterName, StoreHouse storeHouse) {
this.producterName = producterName;
this.storeHouse = storeHouse;
}
public String getProducterName() {
return producterName;
}
public void setProducterName(String producterName) {
this.producterName = producterName;
}
public void producterProduct(){
//生产产品,并放入到仓库中
int i=0;
while(true){
i++;
Product product=new Product(i);
storeHouse.push(product);
System.out.println(producterName+"生产了");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
return;
}
}
}
public void run() {
producterProduct();
}
}
测试类:
package consumerandproducter;
import sun.security.krb5.internal.crypto.t;
public class Test {
public static void main(String[] args) {
StoreHouse storeHouse=new StoreHouse();
Producter producter=new Producter("生产者",storeHouse);
Consumer consumer=new Consumer("消费者",storeHouse);
Thread t1=new Thread(producter);
Thread t2=new Thread(consumer);
t1.start();
t2.start();
/**
* ~输出(随机抽取输出,每次测试的结果可能都有稍许不同):
*
生产者生产了
消费者消费者已经消费product 1
生产者生产了
消费者消费者已经消费product 2
生产者生产了
消费者消费者已经消费product 3
生产者生产了
消费者消费者已经消费product 4
...........
仓库已空,正在等待生产……
生产者生产了
生产者生产了
生产者生产了
生产者生产了
.........
仓库已满,正在等待消费……
消费者消费者已经消费product 14
消费者消费者已经消费product 13
消费者消费者已经消费product 12
消费者消费者已经消费product 11
消费者消费者已经消费product 10
......
*/
}
}
小结:
此问题主要是考察java间多线程通信与资源同步, 其中主要是对于notify与wait方法的使用上,还有对于线程间资源的共享,利用synchronized关键字,对共享资源的锁定,以达到线程同步的效果。
分享到:
相关推荐
生产者消费者模式是java多线程经典的安全,它用到了同步,资源共享,wait,notify等技术。
1.生产者消费者对缓冲区进行互斥操作。 2.缓冲区大小为10,缓冲区满则不允许生产者生产数据,缓冲区空则不允许消费者消费数据。 3.生产者消费者各循环操作50次。 四、设计思路和采取的方案 1.利用windows提供的API...
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消 费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不 用等待消费者处理,直接扔给阻塞队列,消费者不找...
Java写的消费者生产者模式,主要用到线程同步、线程等待和线程唤醒
一、重点知识 isDaemon 判断是否为守护线程。 run方法是不能用synchronized修饰,他是继承来的,不能改变其结构,...stringBuffer中的同步方法,都是非静态的,因为共用一个this锁就可以了,线程进去调用他的一个方法
生产者消费者问题,具体例子为吸烟问题,win10 vs2017编译通过,使用mfc实现线程同步动画展现
通过synchronized关键字实现生产者消费者同步。 其中,有运用到工厂模式,并在该模式中,同样实现了实例的同步
go中的channel是比条件变量更高阶的同步原语。 一个进程内的资源是共享的,进程内执行体之间的协同包含执行体的互斥,通过互斥锁和读写锁实现,包含...生产者消费者模式是线程模型中的经典问题:生产者和消费者在同一时
6、 线程间通信,也叫生产者与消费者问题 15 7、 浅析 Java Thread.join() : java多线程实现主线程等待所有子线程执行完毕 16 8、 线程运行中抛出异常的处理 19 9、 Callable 有返回值的线程 20 10、 Callable结合...
Java线程指南 线程安全与不安全 线程同步synchronized和volatile 线程协作-生产者/消费者模式 Timer和TimerTask 线程池 Callable和Future 锁对象Lock-同步问题更完美的处理方式 Condition-线程通信更高效的方式
Java多线程开发例子,包含线程同步、线程死锁、生产者消费者模式
包括线程和进程的关系,线程的三种创建方式,继承thread,实现runnable接口,实现callable接口,线程同步,生产者消费者模式
生产者-消费者模型:需要设计一个多线程程序,其中有多个生产者和多个消费者,生产者不断产生数据放入共享队列,消费者从队列中取出数据进行消费。 线程池类:需要设计一个线程池类,能够动态管理线程数量,支持可...
将生产和消费分离(解耦),即创建对象和使用对象的功能分离,便于管理 缺点: 1.扩展性弱,如果添加了新的产品,则需要修改工厂方法 使用场景: 适用于产品数量较少,且不经常改变的情况 ...
5.3 阻塞队列和生产者一消费者模式 5.4 阻塞和可中断的方法 5.5 synchronizer 5.6 为计算结果建立高效、可伸缩的高速缓存 第2部分 构建并发应用程序 第6章 任务执行 6.1 在线程中执行任务 6.2 executor 框架 6.3 ...
本工程包含了SpringAOP,死锁,JUC同步锁,读-写同步锁,线程本地使用,JUC线程池和Spring提供的线程池,jdk 1.8中的日期时间API,数据结构中图的实现及操作和广度优先遍历/深度优先遍历(其他待完善),生成XML文件...
5.3 阻塞队列和生产者-消费者模式 5.3.1 示例:桌面搜索 5.3.2 串行线程封闭 5.3.3 双端队列与工作密取 5.4 阻塞方法与中断方法 5.5 同步工具类 5.5.1 闭锁 5.5.2 FutureTask 5.5.3 信号量 5.5.4 栅栏 5.6...
5.3 阻塞队列和生产者-消费者模式 5.3.1 示例:桌面搜索 5.3.2 串行线程封闭 5.3.3 双端队列与工作密取 5.4 阻塞方法与中断方法 5.5 同步工具类 5.5.1 闭锁 5.5.2 FutureTask 5.5.3 信号量 5.5.4 栅栏 5.6...
│ 高并发编程第一阶段26讲、多线程下的生产者消费者模型,以及详细介绍notifyAll方法.mp4 │ 高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │ 高并发编程第一阶段28讲、...