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

Posted 小二郎,上学堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用管程实现生产者消费者模式相关的知识,希望对你有一定的参考价值。

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

这种实现的优点:

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

2.运行速度相对较快

话不多说,直接上代码:

管程类:

package com.brave.test;

import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @描述:管程区
 *
 * @author <p>[email protected]<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>[email protected]<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>[email protected]<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();
    }
}

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

以上是关于使用管程实现生产者消费者模式的主要内容,如果未能解决你的问题,请参考以下文章

请问如何用C语言实现“生产者与消费者问题”?(最好附上完整的C语言源代码)

用C语言实现--生产者与消费者的问题(PV操作)

操作系统王道考研 p27 管程

如何避免可怕的中年危机?成功入职阿里

大厂面试必备:docker退出容器之后会不会保存

Java面试题2020中高级,docker运行本地镜像