zoukankan      html  css  js  c++  java
  • java之生产者与消费者

    package com.produce;
    
    import java.util.LinkedList;
    import java.util.Queue;
    
    /*@author shijin 
    * 生产者与消费者模型中,要保证以下几点: 
    * 1 同一时间内只能有一个生产者生产     生产方法加锁sychronized 
    * 2 同一时间内只能有一个消费者消费     消费方法加锁sychronized 
    * 3 生产者生产的同时消费者不能消费     生产方法加锁sychronized 
    * 4 消费者消费的同时生产者不能生产     消费方法加锁sychronized 
    * 5 共享空间空时消费者不能继续消费     消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行 
    * 6 共享空间满时生产者不能继续生产     生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行    
    */  
      
    //主类  
    public class  ProducerConsumer  
    {  
        public static void main(String[] args)   
        {  
            StackBasket s = new StackBasket();  
            Producer p = new Producer(s);  
            Consumer c = new Consumer(s);  
            Thread tp = new Thread(p);  
            Thread tc = new Thread(c);  
            tp.start();  
            tc.start();  
        }  
    }  
      
    /**
     * 馒头
     * */ 
    class Mantou  
    {  
        private int id;  
          
        Mantou(int id){  
            this.id = id;  
        }  
      
        public String toString(){  
            return "馒头ID" + id;  
        }  
    }  
      
    /**
     * 共享栈空间 仓库
     * */  
    class StackBasket  
    {  
        Queue<Mantou> sm = new LinkedList<Mantou>();  
        int index = 6;  
          
        /**  
        * show 生产方法. 
        * show 该方法为同步方法,持有方法锁; 
        * show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费; 
        * show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态, 
        * show 等生产结束释放同步方法锁后消费才能持有该锁进行消费 
        * @param m 元素 
        * @return 没有返回值  
        */   
      
        public synchronized void push(Mantou m){  
            try{  
                while(index == sm.size()){  
                    System.out.println("!!!!!!!!!生产满了!!!!!!!!!");  
                    this.wait();  
                }  
                this.notify();  
            }catch(InterruptedException e){  
                e.printStackTrace();  
            }catch(IllegalMonitorStateException e){  
                e.printStackTrace();  
            }  
            //此处可执行逻辑操作,如从数据库取出数据  
            sm.offer(m);
            System.out.println("生产了:" + m + " 仓库有:" + sm.size() + "个馒头");  
        }  
      
        /**  
        * show 消费方法 
        * show 该方法为同步方法,持有方法锁 
        * show 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产; 
        * show 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态 
        * show 等消费结束释放同步方法锁后生产才能持有该锁进行生产 
        * @param b true 表示显示,false 表示隐藏  
        * @return 没有返回值  
        */   
        public synchronized Mantou pop(){  
            try{  
                while(sm.size() == 0){  
                    System.out.println("!!!!!!!!!消费光了!!!!!!!!!");  
                    this.wait();  
                }  
                this.notify();  
            }catch(InterruptedException e){  
                e.printStackTrace();  
            }catch(IllegalMonitorStateException e){  
                e.printStackTrace();  
            }  
            Mantou mantou=sm.poll();
         //此处可执行逻辑代码,如将数据更新回数据库 System.out.println(
    "消费了:" + mantou + " 仓库有:" + sm.size() + "个馒头");   return mantou; } } /** * 生产者 * */ class Producer implements Runnable { StackBasket ss = new StackBasket(); Producer(StackBasket ss){ this.ss = ss; } /** * show 生产进程. */ public void run(){ for(int i = 0;i < 20;i++){ Mantou m = new Mantou(i); ss.push(m); // System.out.println("生产了:" + m + " 共" + ss.index + "个馒头"); // 在上面一行进行测试是不妥的,对index的访问应该在原子操作里,因为可能在push之后此输出之前又消费了,会产生输出混乱 try{ Thread.sleep((int)(Math.random()*500)); }catch(InterruptedException e){ e.printStackTrace(); } } } } /** * 消费者 * */ class Consumer implements Runnable { StackBasket ss = new StackBasket(); Consumer(StackBasket ss){ this.ss = ss; } /** * show 消费进程. */ public void run(){ for(int i = 0;i < 20;i++){ Mantou m = ss.pop(); //System.out.println("消费了:---------" + m + " 共" + ss.index + "个馒头"); //同上 在上面一行进行测试也是不妥的,对index的访问应该在原子操作里,因为可能在pop之后此输出之前又生产了,会产生输出混乱 try{ Thread.sleep((int)(Math.random()*1000)); }catch(InterruptedException e){ e.printStackTrace(); } } } }

    输出结果:

    !!!!!!!!!消费光了!!!!!!!!!
    生产了:馒头ID0 仓库有:1个馒头
    消费了:馒头ID0 仓库有:0个馒头
    生产了:馒头ID1 仓库有:1个馒头
    生产了:馒头ID2 仓库有:2个馒头
    生产了:馒头ID3 仓库有:3个馒头
    消费了:馒头ID1 仓库有:2个馒头
    生产了:馒头ID4 仓库有:3个馒头
    消费了:馒头ID2 仓库有:2个馒头
    生产了:馒头ID5 仓库有:3个馒头
    消费了:馒头ID3 仓库有:2个馒头
    生产了:馒头ID6 仓库有:3个馒头
    生产了:馒头ID7 仓库有:4个馒头
    生产了:馒头ID8 仓库有:5个馒头
    消费了:馒头ID4 仓库有:4个馒头
    生产了:馒头ID9 仓库有:5个馒头
    生产了:馒头ID10 仓库有:6个馒头
    !!!!!!!!!生产满了!!!!!!!!!
    消费了:馒头ID5 仓库有:5个馒头
    生产了:馒头ID11 仓库有:6个馒头
    !!!!!!!!!生产满了!!!!!!!!!
    消费了:馒头ID6 仓库有:5个馒头
    生产了:馒头ID12 仓库有:6个馒头
    !!!!!!!!!生产满了!!!!!!!!!
    消费了:馒头ID7 仓库有:5个馒头
    生产了:馒头ID13 仓库有:6个馒头
    消费了:馒头ID8 仓库有:5个馒头
    消费了:馒头ID9 仓库有:4个馒头
    生产了:馒头ID14 仓库有:5个馒头
    生产了:馒头ID15 仓库有:6个馒头
    消费了:馒头ID10 仓库有:5个馒头
    生产了:馒头ID16 仓库有:6个馒头
    !!!!!!!!!生产满了!!!!!!!!!
    消费了:馒头ID11 仓库有:5个馒头
    生产了:馒头ID17 仓库有:6个馒头
    !!!!!!!!!生产满了!!!!!!!!!
    消费了:馒头ID12 仓库有:5个馒头
    生产了:馒头ID18 仓库有:6个馒头
    消费了:馒头ID13 仓库有:5个馒头
    生产了:馒头ID19 仓库有:6个馒头
    消费了:馒头ID14 仓库有:5个馒头
    消费了:馒头ID15 仓库有:4个馒头
    消费了:馒头ID16 仓库有:3个馒头
    消费了:馒头ID17 仓库有:2个馒头
    消费了:馒头ID18 仓库有:1个馒头
    消费了:馒头ID19 仓库有:0个馒头
  • 相关阅读:
    MySQL "show users"
    MySQL
    A MySQL 'create table' syntax example
    MySQL backup
    MySQL show status
    Tomcat, pathinfo, and servlets
    Servlet forward example
    Servlet redirect example
    Java servlet example
    How to forward from one JSP to another JSP
  • 原文地址:https://www.cnblogs.com/zhuawang/p/3750614.html
Copyright © 2011-2022 走看看