【天天动听】一道面试题分享.

最近去天天动听面试,出了以下编程题目.

大概是这样的.

一个生产者进程,一个消费者进程,生产者不断生产产品,消费者不断消费产品,产品量为N.

要求设计这两个进程使其满足如下要求.

1,生产顺序按照队列的方式,先进先出.

2,生产和消费可以同时进行

3 ,当生产容量满了后,不能继续生产,消费完了后不能继续消费

4,当生产容量满了或者消费完了,要节约CPU开销(不能使用sleep())

5,尽量少定义变量,高效率实现.

 

分析:(声明一下,可能下面内容有不对的地方,望各位指教)

这是一道线程间的同步和互斥问题.下面来对5个小求做下分析:

要求1生产顺序按照队列的方式,先进先出.这个要求其实不难实现,产品先放入第一个位置,然后当第二个产品生产出来后要把之前的第一个产品放到第二个位置上面去,刚才生产出来的产品放在第一个位置上,之后依次类推.

要求2生产和消费可以同时进行,这是考多线程.

要求3当生产容量满了后,不能继续生产,消费完了后不能继续消费.这个就是涉及到线程间的同步了.

要求4,当生产容量满了或者消费完了,要节约CPU开销(不能使用sleep()),这个是对要求3作了更进一步的要求,要求使用java中wait让线程挂起,不消耗cpu.

要求5,尽量少定义变量,高效率实现.这个应该是使答案产生亮点的地方

好了5个要求的分析完了下面来看看这道题实现.

这张图作为参考.

首先是生产线程的实现:

/*
 * 生产线程类
 */
public class Producer {
	private Thread produceThread = new Thread(){

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			while(true){
				synchronized (Eviroment.obj) {						//为了线程间互斥进行,防止同时操作index
				if(Eviroment.index < Eviroment.N){	
					try {
						sleep(200);				//这不是题目中要求的不能用的sleep(),仅仅是为了方便观察结果(因为生产一个产品和消费一个产品时间不同的话,输出结果会更明显)
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					//moving index
					Eviroment.index++;
					System.out.println("produce new product numbur: "+ Eviroment.index);
					Eviroment.obj.notify();							//当生产出一件产品后通知消费线程可以消费了.(当然这是在消费者线程消费完产品,处于wait状态才有效)
				}
				if(Eviroment.index == Eviroment.N -1){			    //生产的产品已装满仓库
					try {
						System.out.println("produceThread wait");	
						Eviroment.obj.wait();						//挂起线程	
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}					
				}
			
				}
			}
		}
		
	};
	public void startProduceThread(){
		produceThread.start();
	}
}

然后是消费线程的实现

/*
 * 消费线程类
 */
public class Consumer {
	private Thread ConsumerThread = new Thread(){

		@Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			while(true){
				synchronized (Eviroment.obj) {						//为了线程间互斥进行,防止同时操作index
				if(Eviroment.index >= 0){
					try {
						sleep(500);	//这不是题目中要求的不能用的sleep(),仅仅是为了方便观察结果(因为生产一个产品和消费一个产品时间不同的话,输出结果会更明显)
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("consume product numbur: "+ Eviroment.index);
					//moving index
					Eviroment.index--;
					Eviroment.obj.notify();				//当消费一件产品后,说明仓库有空余位置了,通知消费线程可以生产了.
				}
				if(Eviroment.index == -1){
					try {
						System.out.println("ConsumerThread wait");
						Eviroment.obj.wait();			//消费者线程挂起					
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
				}
			}
		}
		
	};
	public void startConsumeProduct(){
		ConsumerThread.start();
	}
}

最后我写了个环境类,主要是用于公用变量的创建和线程的启动

/*
 * 这是生产环境,主要是放些生产线程和消费线程同时用到的变量,
 * 我们的主线程就在这个类中去启动,然后分别启动生产线程和消费线程
 */
public class Eviroment {
	public static Object obj = new Object();		//互斥对象
	public static int index = -1;					//index表示当前有产品的位置
	public static int N = 10;						//N代表仓库最大容量
	public static void main(String [] args){
		Producer pro = new Producer();				
		Consumer con = new Consumer();
		pro.startProduceThread();					//开始生产线程
		con.startConsumeProduct();					//开始消费线程
	}
}

最后说明一点:在实现过程中,我并没有去写产品的生产过程相关的代码,因为我觉得这并不是这道题的精髓(我们通过index去判断现在生产的产品数量.)

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值