金典面试题之----给我实现一个生产者消费者线程

本文通过分析面包的生产与消费过程,详细解释并实现了一个生产者消费者线程模型,旨在帮助初级开发者深入理解该模型涉及的多线程、栈、设计模式等基础知识。通过实例代码和注释,使读者能够更好地掌握并自行实现这一经典面试题。
摘要由CSDN通过智能技术生成

特别是在初级开发的面试中,面试官可能会让我们实现一个生产者消费者线程,因为这个模型其实能考查到比较多的基础知识,比如多线程、栈、设计模式等等之类的。拿到这个问题,其实我们的第一反应是不难,但是要立刻写出来又感觉无从下手,因为要实现这个模型,其实过程还是比较繁琐的,代码量相比其他算法来说也大一些,可能有些初级开发者没有真正理解到这个模型的情况下,其实是背的代码,因为上述原因,时间久了肯定忘了代码怎么实现的,所以感觉自己会,就是写不出来?。

下面我以面包的生产、消费过程为例,引用生活中的例子,添加通俗易懂的注释,为大家实现一下这个模型,我觉得大家完全可以就按照面包的生产、消费过程来理解这个模型,其实就很好理解了,今后自己实现的时候也可以按照这个过程将代码实现出来:

package com.zhangdeshuai;

/**
 * 说明:生产作者消费者模型中需要有这些对象:生产者、消费者、面包、装面包的容器-盘子(栈结构),所以创建一个生产者消费者模型需要创建以下类:
 * 1、消费生产标的物类,即面包	Bread
 * 2、模拟栈类,即盘子 Plate
 * 3、生产者类  Product
 * 4、消费者类 Consum
 * 5、主函数类,创建线程启用生产者、消费者
 * @author 章德帅
 *
 */
public class ProductionAndConsumption {

	public static void main(String[] args) {
		Plate plate = new Plate();  //创建面包盘
		Product product = new Product(plate); //创建生产者,生产者需要拿到面包盘用来装面包
		Consum consum = new Consum(plate);    //创建消费者,消费者需要拿到面包盘从中取面包
		Thread productThread = new Thread(product);  //创建生产者线程,使用线程创建的第二种方式
		Thread consumThread = new Thread(consum);    //创建消费者线程,使用线程创建的第二种方式
		//启用线程
		productThread.start();
		consumThread.start();
	}
}	
	/*
	 * 生产消费标的物:面包Bread类
	 */
	class Bread{
		int num;
		Bread(int num){//new Bread(i)时调用构造方法注入num,标注这是第几个面包
			this.num = num;
		}
		public String toString(){//重写toString()是为了打印出这是第几个面包
			return "第"+num+"个面包";
		}
	}
	
	
	/*
	 * 创建盘子Plate类装面包(栈结构),需要实现装入和取出的方法
	 */
	class Plate{
		int index;
		Bread []  breads = new Bread[5]; //首先定义盘子大小,一盘能装5个面包
		//装入面包
		public synchronized void push(Bread bread){
			while(index == breads.length){//当index=5时说明这已经是第六个面包了,盘子已经装不下了,要等待消费者取出面包
				try {
					this.wait();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			this.notify();//唤醒在此对象监视器上等待的单个线程,即生产者线程
			breads[index] = bread;
			index++;
		}
		//取出面包
		public synchronized Bread pop(){
			while(index == 0){//当index=0时说明盘子里已经没有面包可以取了,要等待生产者装入面包
				try {
					this.wait();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			this.notify();//唤醒在此对象监视器上等待的单个线程,即消费者线程
			return breads[--index];//因为在装入后执行了index++,但breads[index++]位置上还没有面包,所以先--index才能取到当前面包
		}
	}
	
	/*
	 * 生产者Product类
	 */
	class Product implements Runnable{
		Plate plate = null;  
		Bread bread = null;
		Product(Plate plate){
			this.plate = plate;  //生产者拿到别人递来的盘子
		}
		@Override
		public void run() {
			for(int i=0;i<20;i++){
				bread = new Bread(i); //生产者生产面包
				plate.push(bread);    //生产者将生产的面包放进盘子
				System.out.println("生产者生产了:"+bread);
				try {
					Thread.sleep(10);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	
	/*
	 * 消费者Consum类
	 */
	class Consum implements Runnable{
		Plate plate = null;
		Bread bread = null;
		Consum(Plate plate){
			this.plate = plate;//消费者拿到别人递来的面包盘
		}
		@Override
		public void run() {
			for(int i=0;i<20;i++){
				bread = plate.pop();//消费者从盘子里拿出一个面包
				System.out.println("消费者消费了:"+bread);
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值