生产-消费者的两种实现方式

来源:互联网 发布:php 倒计时功能 编辑:程序博客网 时间:2024/05/22 17:03

第一种:
Storage:

public class Storage {    private final int MAX_SIZE = 100;    private LinkedList<Object> list = new LinkedList<>();    public void produce(int num){        synchronized (Storage.class){            for(int i=0;i<num;i++){                if(list.size()+1>MAX_SIZE){                    System.out.println("此时库存量为:"+list.size()+"已达到最大容量!不能进行生产操作");                    try                    {                        Storage.class.wait();                    }                    catch (InterruptedException e)                    {                        e.printStackTrace();                    }                }else{                    list.add(new Object());                    System.out.println("已经生产了1个产品,现在库存量为"+list.size());                }            }            Storage.class.notifyAll();        }    }    public void consume(int num){        synchronized (Storage.class){            for(int i=0;i<num;i++){                if(list.size()==0){                    System.out.println("此时库存量为0,不能进行消费操作");                    try                    {                        Storage.class.wait();                    }                    catch (InterruptedException e)                    {                        e.printStackTrace();                    }                }else{                    list.remove();                    System.out.println("已经消费了1个产品,现在库存量为"+list.size());                }            }            Storage.class.notifyAll();        }    }    public int getMAX_SIZE() {        return MAX_SIZE;    }    public LinkedList<Object> getList() {        return list;    }    public void setList(LinkedList<Object> list) {        this.list = list;    }}

Producer:

public class Producer extends Thread{    // 每次生产的产品数量    private int num;    // 所在放置的仓库    private Storage storage;    // 构造函数,设置仓库    public Producer(Storage storage)    {        this.storage = storage;    }    // 线程run函数    public void run()    {        produce(num);    }    // 调用仓库Storage的生产函数    public void produce(int num)    {        storage.produce(num);    }    // get/set方法    public int getNum()    {        return num;    }    public void setNum(int num)    {        this.num = num;    }    public Storage getStorage()    {        return storage;    }    public void setStorage(Storage storage)    {        this.storage = storage;    }}

Consumer:

public class Consumer extends Thread{    // 每次消费的产品数量    private int num;    // 所在放置的仓库    private Storage storage;    // 构造函数,设置仓库    public Consumer(Storage storage)    {        this.storage = storage;    }    // 线程run函数    public void run()    {        consume(num);    }    // 调用仓库Storage的生产函数    public void consume(int num)    {        storage.consume(num);    }    // get/set方法    public int getNum()    {        return num;    }    public void setNum(int num)    {        this.num = num;    }    public Storage getStorage()    {        return storage;    }    public void setStorage(Storage storage)    {        this.storage = storage;    }

Test:

public class Test{    public static void main(String[] args)    {        // 仓库对象        Storage storage = new Storage();        // 生产者对象        Producer p1 = new Producer(storage);        Producer p2 = new Producer(storage);        Producer p3 = new Producer(storage);        Producer p4 = new Producer(storage);        // 消费者对象        Consumer c1 = new Consumer(storage);        Consumer c2 = new Consumer(storage);        Consumer c3 = new Consumer(storage);        // 设置生产者产品生产数量        p1.setNum(10);        p2.setNum(10);        p3.setNum(10);        p4.setNum(10);        // 设置消费者产品消费数量        c1.setNum(50);        c2.setNum(20);        c3.setNum(30);        // 线程开始执行        c1.start();        c2.start();        c3.start();        p1.start();        p2.start();        p3.start();        p4.start();    }}

测试结果:

Thread[Thread-4,5,main]此时库存量为0,不能进行消费操作Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为1Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为2Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为3Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为4Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为5Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为6Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为7Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为8Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为9Thread[Thread-2,5,main]已经生产了1个产品,现在库存量为10Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为11Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为12Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为13Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为14Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为15Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为16Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为17Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为18Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为19Thread[Thread-0,5,main]已经生产了1个产品,现在库存量为20Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为21Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为22Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为23Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为24Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为25Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为26Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为27Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为28Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为29Thread[Thread-3,5,main]已经生产了1个产品,现在库存量为30Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为29Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为28Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为27Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为26Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为25Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为24Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为23Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为22Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为21Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为20Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为19Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为18Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为17Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为16Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为15Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为14Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为13Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为12Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为11Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为10Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为9Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为8Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为7Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为6Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为5Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为4Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为3Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为2Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为1Thread[Thread-6,5,main]已经消费了1个产品,现在库存量为0Thread[Thread-5,5,main]此时库存量为0,不能进行消费操作Thread[Thread-4,5,main]此时库存量为0,不能进行消费操作Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为1Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为2Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为3Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为4Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为5Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为6Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为7Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为8Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为9Thread[Thread-1,5,main]已经生产了1个产品,现在库存量为10Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为9Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为8Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为7Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为6Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为5Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为4Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为3Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为2Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为1Thread[Thread-4,5,main]已经消费了1个产品,现在库存量为0Thread[Thread-4,5,main]此时库存量为0,不能进行消费操作Thread[Thread-5,5,main]此时库存量为0,不能进行消费操作

第二种(LinkedBlockingQueue )

只修改Storage其他不变

public class Storage {    private final int MAX_SIZE = 100;    private LinkedBlockingQueue<Object> list = new LinkedBlockingQueue<>(100);    public void produce(int num){           if(list.size()==MAX_SIZE){               System.out.println(Thread.currentThread ()+"此时库存量:"+MAX_SIZE+",容量已满,不能进行生产操作");           }           for(int i=0;i<num;i++){               try{                   list.put(new Object());               }catch (InterruptedException e){                   e.printStackTrace();               }               System.out.println(Thread.currentThread ()+"已经生产了1个商品,此时容量为:"+list.size());           }    }    public void consume(int num){            if(list.size()==0){                System.out.println(Thread.currentThread ()+"此时库存量:0,不能进行消费操作");            }            for(int i=0;i<num;i++){                try{                    list.take();                }catch (InterruptedException e){                    e.printStackTrace();                }                System.out.println(Thread.currentThread ()+"已经消费了1个商品,此时容量为:"+list.size());            }    }    public int getMAX_SIZE() {        return MAX_SIZE;    }    public LinkedBlockingQueue<Object> getList() {        return list;    }    public void setList(LinkedBlockingQueue<Object> list) {        this.list = list;    }}

ps:用LinkedBlockingQueue最后结果打印的时候可能和想象的不一致,是因为如果此时容量已满,在执行put操作时候,内部会调用await()方法,释放了线程的执行权,然后消费者线程拿到执行权调用take()方法,当消费完毕后通知生产者时候会调用signal()方法, 但是这个时候消费者或者还没有打印完我们定义的语句,然后生产者生产又开始打印生产语句,导致输出语句不匹配,所以这个是正常的。

0 0
原创粉丝点击