zoukankan      html  css  js  c++  java
  • 生产者消费者模式

    public class Storage
    {
        // 仓库最大存储量
        private final int MAX_SIZE = 100;
        // 仓库存储的载体
        private LinkedList<Object> list = new LinkedList<Object>();
        // 生产产品
        public synchronized void produce(String producer)////wait和notify notifyAll调用时必须要先上锁,所以要加synchronized
        {
           
                // 如果仓库已满
                while (list.size() == MAX_SIZE)//想想为什么用while而不是用if
                {
      //首先直接上反例,当消费者线程先运行的情况下,由于synchronized存在,这些消费者线程会排着队执行get方法,
      //但是当第一个消费者线程执行到wait判断时,由于没有产品可以get,所以执行wait()导致当前消费者线程放弃了synchronized锁进入阻塞队列,
      //由于synchronized锁是非公平锁,所以接下来会随机选择一个被堵在get方法外的消费者线程执行,接下来的消费者线程也都无一例外地卡在了wait()最后执行的地方。
             //当生产者线程调用put()方法生产完调用notifyAll()之后,上述所有消费者线程进入到就绪队列,等待被调度。
       //如果这里使用的是if而不是while的话,所有消费者这时都会进入到下一行代码,也就是说所有消费者都要执行“拿一个的操作”。
       //假设这时生产者只生产了一个,然后通知一个消费者能过来拿,拿完之后释放锁之后,锁如果落到另一个消费者手里,这时候这个消费者就会拿空。
      
       //另外明明加了synchronized为啥会有两个线程同时在那wait住?
              //因为wait会释放锁!wait会释放锁!!wait会释放锁!!!所以,第一个生产者进来,锁住了,但是碰到wait之后就释放了锁,这时第二个生产者就能进来也执行到wait方法,
             //这样就会产生两个线程同时wait的情况,这样想必大家知道为啥用while而不是if了
                    System.out.println("仓库已满,【"+producer+"】: 暂时不能执行生产任务!");
                    try
                    {
                        // 由于条件不满足,生产阻塞
                        this.wait();  //锁的是类对象,用this
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }//有两个put线程等待,如果不用while用if的话,消费者里唤醒后第二个put线程先拿到锁,他会先添加一个,添加完后把锁给第一个线程,第一个线程已经执行到if结束了,就会再添加一个,就会出现问题
                // 生产产品           
                list.add(new Object());           
                System.out.println("【"+producer+"】:生产了一个产品 【现仓储量为】:" + list.size());
               this.notifyAll();//通知消费者线程进行消费,所以要用notifyAll,如果用notify可能又会唤醒一个生产者  锁的是类对象,用this
           
        }
        // 消费产品
        public void consume(String consumer)
        {
            synchronized (list)
            {
                //如果仓库存储量不足
                while (list.size()==0)
                {
                    System.out.println("仓库已空,【"+consumer+"】: 暂时不能执行消费任务!");
                    try
                    {
                        // 由于条件不满足,消费阻塞
                        list.wait();
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
               
                list.remove();
                System.out.println("【"+consumer+"】:消费了一个产品 【现仓储量为】:" + list.size());
                list.notifyAll();//通知生产者进行生产,  锁的是list 用list
            }
        }
    }
     
    public class Test {
        public static void main(String[] args)
        {
            Storage storage=new Storage();
            for(int i=1;i<6;i++)
            {
                int finalI = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        storage.produce(String.format("生产者%d:", finalI));
                    }
                }).start();
            }
            for(int i=1;i<4;i++)
            {
                int finalI = i;
                new Thread(()-> storage.consume(String.format("消费者%d:", finalI))).start();
            }
        }
    }
    /*  多个生产者消费者线程版本
     public static void main(String[] args)
        {
            Storage storage=new Storage();
            for(int i=1;i<10;i++)
            {
               // int finalI = i;
                new Thread(()-> {
                for (int j = 0; j < 5; j++) {
                  storage.consume("消费者:"+Thread.currentThread().getName());
       }
            }).start();
            }
            for(int i=1;i<20;i++)
            {
               // int finalI = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        storage.produce("生成者:"+Thread.currentThread().getName());
                    }
                }).start();
            }
         
        }*/
  • 相关阅读:
    UVa 1151 Buy or Build【最小生成树】
    UVa 216 Getting in Line【枚举排列】
    UVa 729 The Hamming Distance Problem【枚举排列】
    HDU 5214 Movie【贪心】
    HDU 5223 GCD
    POJ 1144 Network【割顶】
    UVa 11025 The broken pedometer【枚举子集】
    HDU 2515 Yanghee 的算术【找规律】
    Java基本语法
    Java环境变量,jdk和jre的区别,面向对象语言编程
  • 原文地址:https://www.cnblogs.com/wl889490/p/12634569.html
Copyright © 2011-2022 走看看