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

生产者消费者模式是一种常见的设计模式,掌握一种完美,稳定的实现方式非常有用,下面我就使用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();
    }
}

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

时间: 2024-12-12 21:47:19

使用管程实现生产者消费者模式的相关文章

整理整理生产者消费者模式,用通俗的话描述

之前学习多线程问题遇到的最大的难度就是,很多:生产者消费者模式是比较经典的多线程问题,看似 不难,但实际上有很多地方值得注意的. 首先是几个问题 问题1 一共有哪些对象? 生产者与消费者是肯定有的,生产者与消费者之间还有一个缓冲区对象,用以保存生产与消费的目标,还有一个对象就是主线程对象,用来运行多个线程的. 追问:为什么要有一个缓冲区对象? 答:为了实现生产者与消费者解耦,互补依赖或者关联. 追问:每个对象都包含哪些变量与方法? 答:生产者包含缓冲区对象并在run()方法里面执行生产调度命令:

Java并发程序设计(十一)设计模式与并发之生产者-消费者模式

设计模式与并发之生产者-消费者模式 生产者-消费者模式是一个经典的多线程设计模式.它为多线程间的协作提供了良好的解决方案.在生产者-消费者模式中,通常由两类线程,即若干个生产者线程和若干个消费者线程.生产者线程负责提交用户请求,消费者线程则负责具体处理生产者提交的任务.生产者和消费者之间则通过共享内存缓冲区进行通信.

阻塞队列和生产者-消费者模式

阻塞队列提供了可阻塞的put和take方法.如果队列满了put将阻塞到有空间可用,如果队列为空,take将阻塞到有元素可用.队列可以是有界和无界的,无界的队列put将不会阻塞. 阻塞队列支持生产者消费者模式,该模式将找出需要完成的工作,和执行工作分开.生产者-消费者模式能简化开发过程,因为消除了生产者和消费者之间的代码依赖性,此外,该模式还将生产数据的过程和使用数据的过程解耦开来. 在基于阻塞队列构建的生产者-消费者设计中个,当数据生成时,生产者把数据放入队列,当消费者处理数据时,将从队列中获取

并发编程基础之生产者消费者模式

一:概念 生产者消费者模式是java并发编程中很经典的并发情况,首先有一个大的容器,生产者put元素到 容器中,消费者take元素出来,如果元素的数量超过容器的容量时,生产者不能再往容器中put元素 ,处于阻塞状态,如果元素的数量等于0,则消费者不能在从容器中take数据,处于阻塞状态. 二:示例 /** * */ package com.hlcui.main; import java.util.LinkedList; import java.util.concurrent.ExecutorSe

生产者消费者模式

什么是生产者消费者模式   在工作中,大家可能会碰到这样一种情况:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为消费者.在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模式.结构图如下: 生产者消费者模式的优点 1.解耦 假设生产者和消费者分别是两个类.如果让生产者直接调用消费者的某个方法,那

使用BlockingQueue的生产者消费者模式

BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利.使用场景. 首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示: 通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出:在生产者消费者模式中,通过队列的方式可以很方便的实现两者之间的数据共享.强大的BlockingQueue使我们不用关心什么时候需要阻塞线程,什么时候需要唤醒线程. BlockingQueue的

生产者消费者模式(转)

本文转载自博文系列架构设计:生产者/消费者模式.文中对原文格式进行了稍加整理. 概述 今天打算来介绍一下“生产者/消费者模式”,这玩意儿在很多开发领域都能派上用场.由于该模式很重要,打算分几个帖子来介绍.今天这个帖子先来扫盲一把.如果你对这个模式已经比较了解,请跳过本扫盲帖,直接看下一个帖子(关于该模式的具体应用) . 看到这里,可能有同学心中犯嘀咕了:在四人帮(GOF)的23种模式里面似乎没听说过这种嘛!其实GOF那经典的23种模式主要是基于OO的(从书名<Design Patterns: E

生产者消费者模式(吃包子例子)

生产者-消费者问题是一个经典的进程同步问 题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制.在同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空 缓冲区中供消费者线程消费.消费者线程从缓冲区中获得物品,然后释放缓冲区.当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费 者线程释放出一个空缓冲区.当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来. 生产者消费者模式是并发.多线程编程中经典的设计

Java 并发编程(四)阻塞队列和生产者-消费者模式

阻塞队列 阻塞队列提供了可阻塞的 put 和 take 方法,以及支持定时的 offer 和 poll 方法.如果队列已经满了,那么put方法将阻塞直到有空间可以用:如果队列为空,那么take方法将一直阻塞直到有元素可用.队列可以使有界的,也可以是无界的,无界队列永远都不会充满,因此无界队列上的put方法永远不会阻塞.一种常见的阻塞生产者-消费者模式就是线程池与工作队列的组合,在 Executor 任务执行框架中就体现了这种模式. 意义:该模式能简化开发过程,因为他消除了生产者和消费者类之间的代