关闭

【Java多线程】生产者消费者模式

标签: java多线程
159人阅读 评论(0) 收藏 举报
分类:

定义

生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

图解:

这里写图片描述

实例

例1:wait、notify方法

public class ProductorAndConsumerTest {
    public static void main(String[] args) {
        Clerk2 clerk = new Clerk2();

        Productor2 pro = new Productor2(clerk);
        Consumer2 cus = new Consumer2(clerk);

        new Thread(pro, "2生产者 A").start();
        new Thread(cus, "2消费者 B").start();
        new Thread(pro, "2生产者 C").start();
        new Thread(cus, "2消费者 D").start();
    }
}

//店员
class Clerk2{
    private int product = 0;

    //进货
    public synchronized void get(){//循环次数:0
        while(product >= 1){//为了避免虚假唤醒问题,应该总是使用在循环中
            System.out.println("产品已满!");
            try {
                this.wait();
            } catch (InterruptedException e) {
            }
        }

        System.out.println(Thread.currentThread().getName() + " : " + ++product);
        this.notifyAll();
    }

    //卖货
    public synchronized void sale(){//product = 0; 循环次数:0
        while(product <= 0){
            System.out.println("缺货!");

            try {
                this.wait();
            } catch (InterruptedException e) {
            }
        }

        System.out.println(Thread.currentThread().getName() + " : " + --product);
        this.notifyAll();
    }
}

//生产者
class Productor2 implements Runnable{
    private Clerk2 clerk;

    public Productor2(Clerk2 clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
            }

            clerk.get();
        }
    }
}

//消费者
class Consumer2 implements Runnable{
    private Clerk2 clerk;

    public Consumer2(Clerk2 clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            clerk.sale();
        }
    }
}

输出结果:

缺货!
缺货!
2生产者 A : 1
2消费者 D : 0
缺货!
缺货!
2生产者 C : 1
2消费者 B : 0
缺货!
缺货!
2生产者 A : 1
2消费者 D : 0
//中间省略很多行
缺货!
2生产者 C : 1
2消费者 D : 0
缺货!
2生产者 A : 1
2消费者 B : 0

分析:只有当生产者生产了数据,消费者才能消费,否则就缺货!

例2:await、signal方法

public class TestProductorAndConsumerForLock {

    public static void main(String[] args) {
        Clerk clerk = new Clerk();

        Productor pro = new Productor(clerk);
        Consumer con = new Consumer(clerk);

        new Thread(pro, "生产者 A").start();
        new Thread(con, "消费者 B").start();

        new Thread(pro, "生产者 C").start();
        new Thread(con, "消费者 D").start();
    }

}

class Clerk {
    private int product = 0;

    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    // 进货
    public void get() {
        lock.lock();

        try {
            while (product >= 1) { // 为了避免虚假唤醒,应该总是使用在循环中。
                System.out.println("产品已满!");

                try {
                    condition.await();
                } catch (InterruptedException e) {
                }

            }
            System.out.println(Thread.currentThread().getName() + " : "
                    + ++product);

            condition.signalAll();
        } finally {
            lock.unlock();
        }

    }

    // 卖货
    public void sale() {
        lock.lock();

        try {
            while (product <= 0) {
                System.out.println("缺货!");

                try {
                    condition.await();
                } catch (InterruptedException e) {
                }
            }

            System.out.println(Thread.currentThread().getName() + " : "
                    + --product);

            condition.signalAll();

        } finally {
            lock.unlock();
        }
    }
}

// 生产者
class Productor implements Runnable {

    private Clerk clerk;

    public Productor(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            clerk.get();
        }
    }
}

// 消费者
class Consumer implements Runnable {

    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            clerk.sale();
        }
    }

}

输出结果:

缺货!
缺货!
生产者 A : 1
产品已满!
消费者 B : 0
缺货!
缺货!
生产者 C : 1
消费者 B : 0
缺货!
缺货!
生产者 C : 1
产品已满!
消费者 B : 0
缺货!
缺货!
生产者 A : 1
消费者 B : 0
缺货!
缺货!
生产者 C : 1
消费者 B : 0
缺货!
生产者 A : 1
消费者 D : 0
缺货!
生产者 A : 1
消费者 D : 0
缺货!
生产者 C : 1
消费者 D : 0
缺货!
生产者 A : 1
消费者 D : 0
缺货!
生产者 C : 1
消费者 D : 0



本人才疏学浅,若有错误,还请指出
谢谢!

0
0
查看评论

JAVA多线程(三)生产者消费者模式及实现方法

介绍了生产者消费者模式以及实现方法(wait&notify,阻塞队列
  • antony9118
  • antony9118
  • 2016-05-23 15:15
  • 2628

java 多线程并发系列之 生产者消费者模式的两种实现

生产者消费者模式是并发、多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据。 真实世界中的生产者消费者模式 生产者和消费者模式在生活当中随处可见,它描述的是协调与协作的关系。比如一个人正在准备食物(生...
  • yujin753
  • yujin753
  • 2015-05-14 16:59
  • 11801

Java多线程--生产者消费者模型(Semaphore实现)

需求要求:使用2个线程,分别代表:生产者、消费者。让他们并发的去生产、消费产品。生产的总数是不能超过N的。实现思路这里我们使用的是使用信号量去控制线程的生产消费,通过释放令牌的形式去控制生产者消费者的上限。使用互斥锁保证每次最多只有一个角色去修改共享变量。来看张图,一图胜千言。 代码实现代码的注释...
  • qq_24489717
  • qq_24489717
  • 2017-04-12 21:53
  • 813

Java多线程之简单生产者和消费者例子

一,在本例子中,有三个类,dataStore(存放数据类),consumer(消费者),producer(生产者)。 二,看源码例子: 类dataStore: import java.lang.InterruptedException; public class dataStore { ...
  • ganpengjin1
  • ganpengjin1
  • 2015-04-18 15:13
  • 1899

Java多线程-工具篇-BlockingQueue(实现生产者和消费者模式)

前言:      在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成...
  • li12412414
  • li12412414
  • 2017-01-17 09:34
  • 1425

多线程经典案例——生产者/消费者问题的Java实现与详解

生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作...
  • shengwusuoxi
  • shengwusuoxi
  • 2014-04-01 12:37
  • 2619

java模拟生产者与消费者问题(线程同步)

关于生产者与消费者的问题,百度百科上的定义是这样的:生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消...
  • hl17200178
  • hl17200178
  • 2016-10-04 23:32
  • 1911

Java多线程编程中生产者-消费者模式的详解

生产者-消费者模式是一个经典的多线程设计模式,它为多线程的协作提供了良好的解决方案。在生产者-消费者模式中,通常有两类线程,即若干个生产者线程和若干个消费者线程。生产者线程负责提交用户请求,消费者线程负责处理用户请求。生产者和消费者之间通过共享内存缓冲区进行通信。 生产者-消费者模式中的内存缓冲区...
  • ghuiL
  • ghuiL
  • 2014-11-12 15:24
  • 7023

java多线程-专题-聊聊并发(十)生产者消费者模式

本文首发于InfoQ   作者:方腾飞  校对:张龙 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的...
  • L25000
  • L25000
  • 2015-07-27 10:46
  • 1126

线程同步经典案例-生产者与消费者模型-Java

一、相关知识简介      在生产者-消费者模型中,若只使用synchronized关键字实现对象锁,程序在运行中可能会出现以下两种情况: 若生产者的速度大于消费者,那么在消费者来不及取前一个数据之前,生产者又产生了新的数据,于是消费者很可能会跳过前...
  • Xminyang
  • Xminyang
  • 2016-11-18 15:58
  • 1021
    个人资料
    • 访问:66251次
    • 积分:2699
    • 等级:
    • 排名:第15882名
    • 原创:210篇
    • 转载:4篇
    • 译文:1篇
    • 评论:12条
    最新评论