• 使用管程实现生产者消费者模式


    生产者消费者模式是一种常见的设计模式,掌握一种完美,稳定的实现方式非常有用,下面我就使用misa管程实现生产者消费者模式。

    这种实现的优点:

    1.稳定,不会出现死锁现象

    2.运行速度相对较快

    话不多说,直接上代码:

    管程类:

    package com.brave.test;
    
    import java.util.ArrayList;
    import java.util.List;
    /**
     * 
     * @描述:管程区
     *
     * @author <p>1286998496@qq.com<p> brave
     *
     * @date 2017-9-18
     */
    public class Monitor {
    
        /**
         * 互斥量,集合内的成品数量
         */
        private static int mutex = 0;
        /**
         * 缓冲区边界
         */
        private static int N = 20;
        /**
         * 缓冲区
         */
        private static List<String> stuffArr = new ArrayList<String>(N);
        /**
         * 
         * @描述:往缓冲区内存放数据(生产)
         *
         * @author <p>1286998496@qq.com<p> brave
         *
         * @date 2017-9-18
         *
         * @param stuff
         * @throws InterruptedException
         */
        public synchronized void insert(String stuff) throws InterruptedException{
            /**
             * 循环验证,当线程被唤醒后,重新检测条件是否成立
             */
            while(mutex == N){
                System.out.println("缓冲区已满,唤醒消费者");
                notifyAll();
                wait();
                System.out.println("==生产者被唤醒==");
            }
            
            stuffArr.add(stuff);
            //互斥量加一
            mutex++;
            //缓冲区有数据后唤醒消费者
            if(mutex == 1)notifyAll();
        }
        /**
         * 
         * @描述:移除缓冲区内数据(消费)
         *
         * @author <p>1286998496@qq.com<p> brave
         *
         * @date 2017-9-18
         *
         * @return
         * @throws InterruptedException
         */
        public synchronized String remove() throws InterruptedException{
            String result = null;
            while(mutex == 0){
                System.out.println("缓冲区已空,唤醒生产者");
                notifyAll();
                wait();
                System.out.println("==消费者被唤醒==");
            }
            
            result = stuffArr.remove(0);
            
            mutex--;
            if(mutex == N-1)notifyAll();
            return result;
        }
    }

    生产者:

    package com.brave.test;
    
    public class Producers implements Runnable {
    
        private Monitor monitor = null;
        
        public Producers(Monitor monitor) {
            this.monitor = monitor;
        }
        @Override
        public void run() {
            int num = 1;
            while(true){
                
                System.out.println("开始生产商品");
                try {
                    Thread.sleep(1000);
                    System.out.println("商品生产完成:第【" + num + "】件商品");
                    monitor.insert("第【" + num++ + "】件商品");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    消费者:

    package com.brave.test;
    
    public class Consumers implements Runnable {
    
        private Monitor monitor = null;
        
        private String name = null;
        public Consumers(String name ,Monitor monitor) {
            this.monitor = monitor;
            this.name = name;
        }
        @Override
        public void run() {
            while(true){
                
                System.out.println("开始消费商品");
                try {
                    System.out.println(name + "-->商品消费完成:" + monitor.remove() );
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        
    }

    测试类:

    package com.brave.test;
    
    public class Test {
    
        public static void main(String[] args) {
    
            Monitor monitor = new Monitor();
            Thread consumers1 = new Thread(new Consumers("一号消费者",monitor));
            Thread consumers2 = new Thread(new Consumers("二号消费者",monitor));
            Thread producers = new Thread(new Producers(monitor));
            
            producers.start();
            consumers1.start();
            consumers2.start();
        }
    }

    需要注意的是,在测试方法里,每个线程要使用同一个实例。

  • 相关阅读:
    使用Picture Control显示BMP图片
    [转]程序员技术练级攻略
    自绘控件笔记
    VS2010中CMFCToolBar的用法
    我用到的FireFox浏览器插件
    C# 中的 DataTimePicker 控件的时间转换
    MacBook 小白,安装 JDK
    C# Combobox 设置选中项
    Drupal7(2)
    Drupal7(1)
  • 原文地址:https://www.cnblogs.com/zbrave/p/7544316.html
Copyright © 2020-2023  润新知