需求如下:
有一个生产者和一个消费者,生产者不断的生产产品,消费这不断的消费产品.产品总数为N.
1.生产顺序按队列的方式,先进先出.
2.生产者和消费这可以同时进行.
3.当生产者生产了N个产品后不能继续生产,消费者消费完后不能继续消费.
4.当生产完成,或者消费完成时,要节约CPU开支(不能使用Sleep);
5.尽量少定义变量,高效率实现.
说明:花了一个小时实现的,如果有不同的意见,希望大家能够指出,共同学习共同进步.
下面说一下我分析的过程:
题目上说:
1.有一个生产者和消费者,这个告诉我们至少要建立两个线程,一个生产者线程,一个消费者线程
2.由生产顺序:先进先出,告诉我们应该使用一个队列.
3.生产和消费可以同时进行:告诉我们至少我们应该考虑并发的问题,我正在生产时你别来消费.
4.要节约CPU开支和生产,消费完成后不能继续生产或者消费:告诉我们而且不能使用Sleep,那么我们应该想到的是,使用wait或者阻塞队列.
抽象一下模型:创建两个线程,一个用于不断的向集合中添加数据,一个不断的向集合中取除数据,如果集合已满,则进行阻塞,如果取数据是集合为空则仍然进行阻塞.
好了下面贴出源代码,如果中间有什么不明白的大家可以查看java jdk帮助文档,上面都有介绍,我这里就不再说了.
生产者:
package cn.yw.daydayinterviewquestion; import java.util.concurrent.ArrayBlockingQueue; public class MainTest { /** * 程序的入口main方法 * * @param args */ public static void main(String[] args) { final WorkShop workShop = new WorkShop(); // production new Thread() { public void run() { while(true){ try { workShop.production(); Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } }; }.start(); // customer new Thread() { public void run() { while(true){ try { workShop.customer(); Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } }; }.start(); } /** * 车间类 * * @author yw-tony * */ static class WorkShop { private int i = 0; private int countNum = 100;//产品总量 // 产品队列 ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1); //加上互斥技术以防止生产者生产到一半时消费这就消费了. // 生产方法 public synchronized void production() throws Exception{ if (i < countNum) { i++; /*System.out.println("线程" + Thread.currentThread().getName() + "准备生产产品." + i);*/ queue.put(i); System.out.println("线程" + Thread.currentThread().getName() + "生产了产品." + i); }else{ System.out.println("生产完成,等待中...."); queue.take(); } } // 消费方法 public synchronized void customer() throws Exception{ /*countNum--; System.out.println("准备消费产品"+countNum);*/ //消费完成的依据是,消费数等于产品数 Integer c = queue.take();//检索并移除此队列的头部,如果次队列为空,这一直处于等待状态. System.out.println("消费了产品"+c); if(c >= 100){ System.out.println("消费完成,正在等待商品产出....."); } } } }
备注:在这里不用阻塞队列也是可以的,使用线程之间的通信技术一样能够实现,有兴趣的朋友可以写一下,我这里就不写了.