java中使用阻塞队列实现生产这与消费这之间的关系

需求如下:

  有一个生产者和一个消费者,生产者不断的生产产品,消费这不断的消费产品.产品总数为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("消费完成,正在等待商品产出.....");
            }
        }

    }
}

备注:在这里不用阻塞队列也是可以的,使用线程之间的通信技术一样能够实现,有兴趣的朋友可以写一下,我这里就不写了.

   

原文地址:https://www.cnblogs.com/tony-yang-flutter/p/3603688.html