使用ReentrantLock模拟简单生产者和消费者问题

来源:互联网 发布:大数据入门经典书籍 编辑:程序博客网 时间:2024/06/06 18:21

使用ReentrantLock模拟简单生产者和消费者问题


本文主要讲述使用Java的ReentrantLock来实现模拟生产者-消费者的问题,主要经过以下5个过程来完成:
1. 生产商品,向存储商品的数组中添加商品,该过程用ReentrantLock来加锁。
2. 消费商品,从存储商品的数组中消费商品,该过程同样用ReentrantLock来加锁。
3. 用一个生产线程来模拟进行生产商品的操作。
4. 用一个消费线程来模拟进行消费商品的操作。
5. 测试整个生产者-消费者问题的程序。


定义一个BoundedQueue类

BoundedQueue类主要有两个方法add和reduce,对应模拟商品的生产和消费,代码如下:

public class BoundedQueue<T> {    private Object[] products;//存储生产商品的数组products    volatile int count;//数组products数组中已经存储的商品数量    int addIndex, reduceIndex;     Lock lock=new ReentrantLock();    //notFull和notEmpty主要用于实现等待/通知功能    Condition notFull=lock.newCondition();    Condition notEmpty=lock.newCondition();    //对类BoundedQueue的初始化操作    public BoundedQueue(int size){        super();        products=new Object[size];        count=0;        addIndex=0;        reduceIndex=0;    }    //模拟生产者生产商品    public void add(T t) throws InterruptedException{        lock.lock();        try{            while(count==products.length)                notFull.await();//如果products数组已经装满,则生产线程进入等待队列等待,释放lock            products[addIndex]=t;            if(++addIndex==products.length)                addIndex=0;            count++;//products中增加一个新商品            notEmpty.signal();//products中有商品,对消费线程进行通知        }finally{            lock.unlock();//释放lock        }    }    //模拟消费者消费商品    public T reduce() throws InterruptedException{        lock.lock();        try{            while(count==0)                notEmpty.await();//如果products数组存储的商品为空,则消费线程进入等待队列等待,释放lock            Object product=products[reduceIndex];//获取的是Object类型需要强制类型转换            if(++reduceIndex==products.length)                reduceIndex=0;            count--;//products中消费一个商品            notFull.signal();//products还未被沾满,对生产线程进行通知            return (T)product;        }finally{            lock.unlock();//释放lock        }    }    //获取生产者线程    public Thread getProduceThread(BoundedQueue<T> boundedQueue, Object products[])    {        Producer<T> producer=new Producer(boundedQueue, products);        Thread produceThread=new Thread(producer,"produceThread");        return produceThread;    }    //获取消费者线程    public Thread getConsumeThread(BoundedQueue<T> boundedQueue)    {        Consumer<T> consumer=new Consumer(boundedQueue);        Thread consumeThread=new Thread(consumer,"consumeThread");        return consumeThread;    }}

利用线程来模拟生产者

模拟生产者的代码如下:

class Producer<T> implements Runnable{    private BoundedQueue<T> boundedQueue;    private Object[] readyProducts;//准备进行生产的商品    //初始化Producer类    public Producer(BoundedQueue<T> boundedQueue, Object[] readyProducts) {        super();        this.boundedQueue = boundedQueue;        this.readyProducts=new Object[readyProducts.length];        for(int i=0;i<readyProducts.length;i++)            this.readyProducts[i]=readyProducts[i];    }    @Override    public void run() {        // TODO Auto-generated method stub        for(int i=0;i<readyProducts.length;i++)        {            try {                boundedQueue.add((T) readyProducts[i]);                System.out.println(Thread.currentThread().getName()+" has produced ["+(T)readyProducts[i]+"]");//打印生产商品的信息            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        //}    }  }}

利用线程来模拟消费者

模拟消费者的代码如下:

class Consumer<T> implements Runnable{    private BoundedQueue<T> boundedQueue;    private boolean on;//作为开关来关闭消费线程    //初始化Consumer类    public Consumer(BoundedQueue<T> boundedQueue) {        super();        this.boundedQueue=boundedQueue;        this.on = true;    }    @Override    public void run() {        // TODO Auto-generated method stub        while(on)        {            try {                T product=boundedQueue.reduce();                System.out.println(Thread.currentThread().getName()+" has consumed ["+product+"]");//打印消费的商品信息            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    public void closeThread(){        on=false;    }}

进行测试

测试代码如下:

public static void main(String[] args) {        BoundedQueue<String> boundedQueue=new BoundedQueue<>(3);        String fruits[]=new String[]{"apple","banana","peach","watermelon","pear","grape"};        Thread produceThread=boundedQueue.getProduceThread(boundedQueue, fruits);        Thread consumeThread=boundedQueue.getConsumeThread(boundedQueue);        produceThread.start();        consumeThread.start();}

0 0