多线程:生产者/消费者模式

生产者/消费者模式

实际上,很多后台服务程序并发控制的基本原理都可以归纳为生产者/消费者模式。

生产者消费问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可以分为两类:

  1. 采用某种机制保护生产者和消费者之间的同步;
  2. 生产者和消费者之间建立一个管道。

第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。

第二种管道缓冲不易控制,被传输数据对象不易于封装,实用性不强。

同步问题的核心在于:如何保证同一资源被多个线程并发访问时的完整性。

准确说应该是"生产者-消费者-仓库"模型,离开了仓库,生产者消费者模型就显得没有说服力了。

对于此模型,应该明确一下几点:

  1. 生产者仅仅在仓库未满时候生产,仓满则停止生产。
  2. 消费者仅仅在仓库有产品的时候才能消费,仓空则等待。
  3. 当消费者发现仓库没产品可消费时候会通知生产者生产。
  4. 生产者在生产出可消费产品时候,应该通知等待的消费者取消费。

光看文字可能不太好理解,下面是案例:

1、生产者模块

package com.edu.qwd;

import javax.swing.plaf.synth.SynthSpinnerUI;

//生产者线程要执行的任务
public class Producer implements Runnable {
 private Clerk cl;
 public Producer(Clerk cl){
  this.cl=cl;
 }
 
 public void run(){
  System.out.println("生产者开始生产产品!");
  while(true){
   try {
    Thread.sleep((int)(Math.random()*10)*100);
   } catch (InterruptedException e) {
    // TODO 自动生成的catch块
    e.printStackTrace();
   }
   cl.addproduct();//生产产品
  }
 }

}

2、缓冲电力模块

package com.edu.qwd;

public class Clerk {
 private int product=0;//产品默认为0;
 //生产者生成出来的产品交给店员
 public synchronized void addproduct(){
  if(this.product>=20){
   try {
    wait();//产品已满,请稍等再生产
   } catch (InterruptedException e) {
    //自动生成的catch块
    e.printStackTrace();
   }
  }else{
   product++;
   System.out.println("生产者生产产品"+product+"个产品。");
   notifyAll();//通知等待区的消费者今天取产品了
  }
 }
 
 //消费者从店员处取产品
 public synchronized void getProduct(){
  if(this.product<=0){
   try {
    wait();//产品没有货了,请稍等再取
   } catch (InterruptedException e) {
    // TODO 自动生成catch块
    e.printStackTrace();
   }
  }else{
   System.out.println("消费者取走了第"+product+"个产品");
   product--;
   notify();//通知等待区的生产者可以生产产品
  }
 }
}

3、消费者模块

package com.edu.qwd;
//消费者线程要执行的任务
public class Consumer implements Runnable{
 private Clerk cl;
 public Consumer(Clerk cl){
  this.cl=cl;
 }
 public void run(){
  System.out.println("消费者开始取走产品!");
  while(true){
   try {
    Thread.sleep((int)(Math.random()*10)*100);
   } catch (InterruptedException e) {
    // TODO 自动生成的catch块
    e.printStackTrace();
   }
   cl.getProduct();//取走产品
  }
 }

}

4、最后Main方法输出就可以了

package com.edu.qwd;

public class Main {
public static void main(String[] args) {
 //自动生成的方法存根
 Clerk cl=new Clerk();
 Thread prt=new Thread(new Producer(cl));//生产者线程
 Thread cot=new Thread(new Consumer(cl));//消费者线程
 prt.start();
 cot.start();
 }
}

使用了生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体(常见并发类型有进程和线程两种)。生产者把制造出来的数据往缓冲区一丢,就可以去生产下一个数据。基本上不用依赖消费者的处理数据。

时间: 2024-08-25 06:06:18

多线程:生产者/消费者模式的相关文章

java多线程 生产者消费者模式

package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static void main(String[] args) { Godown godown = new Godown(50); for (int i = 0; i < 5; i++) { new ProducerThread(i * 10, godown).start(); new ConsumerThre

多线程生产者消费者模式

闲着没事,写了个生产者消费者模式玩玩,顺便熟悉下notify的用法. package sync; public class Test { public static void main(String[] args) { Test test = new Test(); Producer producer = test.new Producer(); producer.start(); Consumer consumer = test.new Consumer(); consumer.setName

java 多线程-生产者消费者模式-管程法

生产者消费者模式管程法通过容器中介,将数据放入和取出 wait()导致当前线程等待,直到另一个线程调用该对象的notify()或notyfyAll()方法notify()唤醒正在等待对象监视器的单个线程,notifyAll()唤醒正在等待对象监视器的所有线程 public class tuble { public static void main(String[]args) { SynContainer container=new SynContainer(); new Productor(co

多线程生产者/消费者模式实现

参考书籍<java多线程编程核心技术> 都是基于wait/notify实现的 一个生产者和一个消费者:操作值 1 package com.qf.test10.pojo; 2 3 /** 4 * @author qf 5 * @create 2018-09-18 15:59 6 */ 7 public class Entity { 8 public static String value = ""; 9 } 1 package com.qf.test10; 2 3 impor

Java多线程-生产者/消费者模式实现

单生产者与单消费者 示例: public class ProduceConsume { public static void main(String[] args) { String lock = new String(""); Produce produce = new Produce(lock); Consume consume = new Consume(lock); new Thread(() -> { while (true) { produce.setValue();

多线程的并发执行应用(生产者消费者模式)

在实际的开发中我们为了提高CPU的利用率,也提高程序的执行效率,我们经常使用多线程进行对数据进行并发处理,下面我举一个多线程并发执行的实例,大致意思就是 一个简单的生产者消费者模式,二个线程进行存数据,一个线程进行取数据. import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueueTest { /** * @param a

多线程之生产者消费者模式

最近在项目中需要使用使用多线程实现一种功能,和生产者消费者模式类似,因此,学习了下生产者消费者模式的多线程实现.在生产者消费者模式中,通常有两类线程, 即若干个生产者线程和若干个消费者线程.生产者线程负责提交用户请求,消费者线程则负责处理生产者提交的任务.生产者和消费者之间则通过共享内存缓冲区进行通信. 在这里我们选择BlockingQueue做为共享内存缓冲区. 首先,我们构建生产者生产的,和消费者需要处理的数据PCData,即相关任务数据. public class PCData { pri

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

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这种生产消费能力不均衡的问题,所以便有了生产者和消费者模式. 什么是生

java 多线程 22 :生产者/消费者模式 进阶 利用await()/signal()实现

java多线程15 :wait()和notify() 的生产者/消费者模式 在这一章已经实现了  wait/notify 生产消费模型 利用await()/signal()实现生产者和消费者模型 一样,先定义一个缓冲区: public class ValueObject { public static String value = ""; } 换种写法,生产和消费方法放在一个类里面: public class ThreadDomain41 extends ReentrantLock {