• 多线程模拟实现生产者/消费者模型 (借鉴)


     在生产者/消费者模型中,生产者Producer负责生产数据,而消费者Consumer负责使用数据。多个生产者线程会在同一时间运行,生产数据,并放到内存中一个共享的区域。期间,多个消费者线程读取内存共享区,消费里面的数据。

    分析

    在下面Java应用程序中,生产者线程向一个线程安全的堆栈缓冲区中写(PUSH)数据,消费者从该堆栈缓冲区中读(POP)数据,这样,这个程序中同时运行的两个线程共享同一个堆栈缓冲区资源。

    类Producer是生产者模型,其中的run方法中定义了生产者线程所做的操作,循环调用push()方法,将生产的100个字母送入堆栈中,每次执行完push操作后,调用sleep方法睡眠一段随机时间。

    类Consumer是消费者模型,循环调用pop方法,从堆栈取出一个字母,一共取100次,每次执行完push操作后,调用sleep方法睡眠一段随机时间

    同步堆栈类SynchronizedStack

    package com.ailk.biapp.ci.ProducerAndConsumer;
    
    public class SynchronizedStack {
        private int index = 0;
        private int size = 100;
        //共享内存区
        private char[] data;
        
        public SynchronizedStack(int size){
            System.out.println("栈被创建");
            this.size = size;
            data = new char[size];
        }
        
         /**
         * 生产数据
         * 
         * @param c
         */
        public synchronized void push(char c){
            while (index == size){
                try{
                    System.err.println("生产数据满了");
                    this.wait();//等待,直到有数据出栈
                }catch(InterruptedException e){
                     Thread.currentThread().interrupt();
                     e.printStackTrace();
                }
            }
            data[index] = c;
            index++;
            this.notify();//通知其他线程把数据出栈 
        }
        
        /**
         * 消费数据
         * 
         * @return
         */
        public synchronized char pop(){
            while (index == 0){
                try{
                    System.err.println("栈空了");
                    this.wait();// 等待,直到有数据出栈
                }catch(InterruptedException e){
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            }
            index --;//指针向下移动
            char ch = data[index];
            this.notify();//通知其他线程把数据入栈
            return ch;
        }
        
        //显示堆栈内容
        public synchronized void print(){
            for(int i = 0; i < data.length; i++){
                System.out.println(data[i]);
            }
            System.out.println();
            this.notify();// 通知其它线程显示堆栈内容
        }
        
    }

    生产者Product

    package com.ailk.biapp.ci.ProducerAndConsumer;
    
    public class Producer implements Runnable{
        private SynchronizedStack stack;
        
        public Producer(SynchronizedStack s){
            stack = s;
        }
        
        public void run(){
            char ch;
            for(int i = 0; i< 100; i++){
                //随机产生100个字符
                ch = (char) (Math.random() * 26 + 'A');
                stack.push(ch);
                System.out.println("Produced:" + ch);
                try{
                    //每一个字符线程就休眠一下
                     Thread.sleep((int) (Math.random() * 1000));
                }catch (InterruptedException e) {
            }
        }
        }
    }

    消费者Consumer

    package com.ailk.biapp.ci.ProducerAndConsumer;
    
    public class Consumer implements Runnable{
        private SynchronizedStack stack;
        
        public Consumer(SynchronizedStack s){
            stack = s;
        }
        
        public void run() {
            char ch;
            for(int i = 0 ; i < 100; i++){
                ch = stack.pop();
                System.out.println("Consumed:" + ch);
            }
            try{
                 Thread.sleep((int) (Math.random() * 1000));
            }catch(InterruptedException e){
                
            }
            
        }
    
    }

    测试:

    package com.ailk.biapp.ci.ProducerAndConsumer;
    
    public class ProductConsumerTest {
        public static void main(String args[]){
            // 下面的消费者类对象和生产者类对象所操作的是同一个同步堆栈对象
            SynchronizedStack stack = new SynchronizedStack(5);
            Runnable source = new Producer(stack);
            Runnable sink = new Consumer(stack);
    
            Thread t1 = new Thread(source);
            Thread t2 = new Thread(sink);
            t1.start();
            t2.start();
        }
    }

    借鉴于:http://www.cnblogs.com/linjiqin/archive/2011/04/15/2016820.html

  • 相关阅读:
    【查漏补缺】普通类中获取有注解的类
    【线程池原理】线程池的原理及实现
    【SpringCloud微服务实战学习系列】客户端负载均衡Spring Cloud Ribbon
    【SpringCloud错误】错误记录
    【SpringCloud微服务实战学习系列】服务治理Spring Cloud Eureka
    【SpringBoot整合Elasticsearch】SpringBoot整合ElasticSearch
    【SpringCloud微服务实战学习系列】配置详解
    【SpringCloud微服务实战学习系列】创建应用及解析
    【微服务系列】Spring SpringMVC SpringBoot SpringCloud概念、关系及区别
    【错误整理】ora-00054:resource busy and acquire with nowait specified解决方法【转】
  • 原文地址:https://www.cnblogs.com/yangsy0915/p/5022357.html
Copyright © 2020-2023  润新知