多线程生产者和消费者

多线程系列(十二) -生产者和消费者模型 在 Java 多线程编程中,还有一个非常重要的设计模式,它就是:生产者和消费者模型。 阅读详情

LinkedBlockingQueue应用--生产消费模型简单实现  

之前介绍时LinkedBlockingQueue提到了Queue主要应用于“生产消费模型”的实现。在尝试分析 ConcurrentLinkedQueue之前,写了个简陋的“生产消费模型”的实现。分享的同时加深对LinkedBlockingQueue的印 象,顺便再说说其特性:
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author: yanxuxin
 * @date: 2010-1-25
 */
public class ModelSample {
 /** 线程池提交的任务数*/
 private final int taskNum = Runtime.getRuntime().availableProcessors() + 1;
 /** 用于多线程间存取产品的队列*/
 private final LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(16);
 /** 记录产量*/
 private final AtomicLong output = new AtomicLong(0);
 /** 记录销量*/
 private final AtomicLong sales = new AtomicLong(0);
 /** 简单的线程起步开关*/
 private final CountDownLatch latch = new CountDownLatch(1);
 /** 停产后是否售完队列内的产品的选项*/
 private final boolean clear;
 /** 用于提交任务的线程池*/
 private final ExecutorService pool;
 /** 简陋的命令发送器*/
 private Scanner scanner;

 public ModelSample(boolean clear) {
  this.pool = Executors.newCachedThreadPool();
  this.clear = clear;
 }

 /**
  * 提交生产和消费任务给线程池,并在准备完毕后等待终止命令
  */
 public void service() {
  doService();
  waitCommand();
 }
 
 /**
  * 提交生产和消费任务给线程池,并在准备完毕后同时执行
  */
 private void doService() {
  for (int i = 0; i < taskNum; i++) {
   if (i == 0) {
    pool.submit(new Worker(queue, output, latch));
   }
   else {
    pool.submit(new Seller(queue, sales, latch, clear));
   }
  }
  latch.countDown();//开闸放狗,线程池内的线程正式开始工作
 }

 /**
  * 接收来自终端输入的终止命令
  */
 private void waitCommand() {
  scanner = new Scanner(System.in);
  while (!scanner.nextLine().equals("q")) {
   try {
    Thread.sleep(500);
   }
   catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  scanner.close();
  destory();
 }

 /**
  * 停止一切生产和销售的线程
  */
 private void destory() {
  pool.shutdownNow(); //不再接受新任务,同时试图中断池内正在执行的任务
  while (clear && queue.size() > 0) {
   try {
    Thread.sleep(500);
   }
   catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  System.out.println("Products:" + output.get() + "; Sales:" + sales.get());
 }

 public static void main(String[] args) {
  ModelSample model = new ModelSample(false);
  model.service();
 }
}

/**
 * 生产者
 * @author: yanxuxin
 * @date: 2010-1-25
 */
class Worker implements Runnable {

 /** 假想的产品*/
 private static final String PRODUCT = "Thinkpad";
 private final LinkedBlockingQueue<String> queue;
 private final CountDownLatch latch;
 private final AtomicLong output;

 public Worker(LinkedBlockingQueue<String> queue, AtomicLong output,CountDownLatch latch) {
  this.output = output;
  this.queue = queue;
  this.latch = latch;
 }

 public void run() {
  try {
   latch.await(); // 放闸之前老实的等待着
   for (;;) {
    doWork();
    Thread.sleep(100);
   }
  }
  catch (InterruptedException e) {
   System.out.println("Worker thread will be interrupted...");
  }
 }

 private void doWork() throws InterruptedException {
  boolean success = queue.offer(PRODUCT, 100, TimeUnit.MILLISECONDS);
  if (success) {
   output.incrementAndGet(); // 可以声明long型的参数获得返回值,作为日志的参数
   // 可以在此处生成记录日志
  }
 }
}

/**
 * 消费者
 * @author: yanxuxin
 * @date: 2010-1-25
 */
class Seller implements Runnable {

 private final LinkedBlockingQueue<String> queue;
 private final AtomicLong sales;
 private final CountDownLatch latch;
 private final boolean clear;

 public Seller(LinkedBlockingQueue<String> queue, AtomicLong sales, CountDownLatch latch, boolean clear) {
  this.queue = queue;
  this.sales = sales;
  this.latch = latch;
  this.clear = clear;
 }

 public void run() {
  try {
   latch.await(); // 放闸之前老实的等待着
   for (;;) {
    sale();
    Thread.sleep(500);
   }
  }
  catch (InterruptedException e) {
   if(clear) { // 响应中断请求后,如果有要求则销售完队列的产品后再终止线程
    cleanWarehouse();
   }
   else {
    System.out.println("Seller Thread will be interrupted...");
   }
  }
 }

 private void sale() throws InterruptedException {
  String item = queue.poll(50, TimeUnit.MILLISECONDS);
  if (item != null) {
   sales.incrementAndGet(); // 可以声明long型的参数获得返回值,作为日志的参数
   // 可以在此处生成记录日志
  }
 }

 /**
  * 销售完队列剩余的产品
  */
 private void cleanWarehouse() {
  try {
   while (queue.size() > 0) {
    sale();
   }
  }
  catch (InterruptedException ex) {
   System.out.println("Seller Thread will be interrupted...");
  }
 }
}

ModelSample是主控,负责生产消费的调度,Worker和Seller分别作为生产者和消费者,并均实现Runnable接口。 ModelSample构造器内的参数clear主要是用于:当主控调用线程池的shutdownNow()方法时,会给池内的所有线程发送中断信号,使 得线程的中断标志置位。这时候对应的Runnable的run()方法使用响应中断的LinkedBlockingQueue的方法(入队,出队)时就会 抛出InterruptedException异常,生产者线程对这个异常的处理是记录信息后终止任务。而消费者线程是记录信息后终止任务,还是消费完队 列内的产品再终止任务,则取决于这个选项值。

    多线程的一个难点在于适当得销毁线程,这里得益于LinkedBlockingQueue的入队和出队的操作均提供响应中断的API,使得控制起来相对的 简单一点。在Worker和Seller中共享LinkedBlockingQueue的实例queue时,我没有使用put或者take在queue满 和空状态时无限制的阻塞线程,而是使用offer(E e, long timeout, TimeUnit unit)和poll(long timeout, TimeUnit unit)在指定的timeout时间内满足条件时阻塞线程。主要因为在于:先中断生产线程的情况下,如果所有的消费线程之前均被扔到等待集,那么无法它 们将被唤醒。而后两者在超时后将自行恢复可运行状态。

    再者看看queue的size()方法,这也是选择LinkedBlockingQueue而不选ArrayBlockingQueue作为阻塞队列的原 因。因为前者使用的AtomicInteger的count.get()返回最新值,完全无锁;而后者则需要获取唯一的锁,在此期间无法进行任何出队,入 队操作。而这个例子中clear==true时,主线程和所有的消费线程均需要使用size()方法检查queue的元素个数。这类的非业务操作本就不该 影响别的操作,所以这里LinkedBlockingQueue使用AtomicInteger计数无疑是个优秀的设计。

    另外编写这个例子时有点玩票的用了CountDownLatch,它的作用很简单。countDown()方法内部计数不为0时,执行了其await() 方法的线程将会阻塞等待;一旦计数为0,这些线程将恢复可运行状态继续执行。这里用它就像一个发令枪,线程池submit任务的新线程在run内被阻塞, 主线程一声令下countDown!这些生产消费线程均恢复执行状态。最后就是命令的实现过于简陋了,如果要响应其他的命令的话可以改造成响应事件处理的 观察者模式,不过它不是演示的重点就从简了。后面就是试着写写ConcurrentLinkedQueue的分析了。
多线程之生产者和消费者模式(信号灯法) ------昨天理解的生产者和消费者模式,今天写一下我对这个模式的想法,然后我利用这个模式写了一个 读取文件的小程序。 ------介绍:生产者和消费者模式,它不是一种设计模式,而是一种解决由多线程引发的同步问题的办法,也称为有限缓冲问题 ------有一块固定容量的缓存区,有多个线程同时访问或操作这个块缓存区,而此时,一个线程称为生产者,生成数据到这块缓存,另一个线程消费者从这个块缓存里读取数据... 阅读详情

相关推荐

java多线程-生产者和消费者问题

经典生产者消费者问题: /* 线程通信的应用 分析: 1.是否是多线程问题?是,生产者线程,消费者线程 2.是否有共享数据?是,产品 3.如何解决线程安全问题?同步机制,有三种方法 4.是否涉及到线程的通信?是 */ public class ProductTest { public static void main(String[] args) { Clerk clerk = new Clerk(); Producer p1 = new Produce

十三月的博客 1792

多线程-生产者和消费者模式的四种实现

什么是生产者和消费者模式: 生产者和消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此并不直接通信,而是通过阻塞队列进行通信,所以生产者生产完数据后不用等待消费者进行处理,而是直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列中获取数据,阻塞队列就相当于一个缓冲区,平衡生产者和消费者的处理能力。 wait/notify和synchronized配合实现: 生产者...

Fly_Fly_Zhang的博客 7204

TI LP87745-Q1汽车雷达PMIC评估:从硬件设计到性能测试全解析

在汽车电子和高级驾驶辅助系统(ADAS)中,电源管理单元(PMIC)是确保传感器稳定可靠运行的核心。其工作原理在于集成多路高效电源转换器(如Buck、Boost)和精密监控电路,通过数字接口实现灵活配置与实时诊断。这项技术的核心价值在于为毫米波雷达等关键负载提供低噪声、高精度、满足严格时序与功能安全(ASIL)要求的供电方案,从而提升整个感知系统的信噪比与可靠性。其典型应用场景包括自动驾驶域控制器、车载传感器融合模块等。本文以德州仪器(TI)的LP87745-Q1专用PMIC及其评估模块(EVM)为例,深入

weixin_27017211的博客 311

Java 多线程模拟生产者和消费者

1.首先是资源类 /** * 资源类 */ public class Res { private String userName; private String sex; // true 生产者等待,消费者消费 private Boolean flag = true; .... get/set方法 .... } 2.生产者类 /* * ...

su1177的博客 312

PE启动盘结合360杀毒离线版:深度清除顽固病毒实战指南

在系统安全维护领域,离线查杀是一种在独立于宿主操作系统的环境下进行病毒扫描和清除的核心技术。其原理是通过一个预启动环境(如PE)加载杀毒软件,从而绕过可能已被感染或受保护的系统核心,直接访问和扫描磁盘文件。这项技术的核心价值在于能够彻底处理那些在正常系统运行时难以清除的深度隐藏病毒、Rootkit和驱动级木马。典型的应用场景包括应对勒索软件、顽固感染型病毒以及系统启动项被劫持等情况。本文以“PE启动盘”和“360杀毒离线版”这一经典组合为例,详细解析了从工具选型、环境部署到深度查杀策略的全流程,为系统维护人

weixin_29741447的博客 410

EPLAN 设备接线图模板制作

属性摆放 设备连接图设置(选项 - - 设置) 连接图生成

weixin_36447711的博客 7864

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

package com.git.base.thread.productandconsumer; /** * 核心实现: * 生产者消费者模式: * 生产一个,消费一个,如果生产未被消费,那么就等待消费后再生产 * 如果消费后,没有下一个生产的,就等待生产后在消费 * Title: DoMain.java * Description: * Copyright: Copyright (

筑梦者 3064

软件工程大作业——图书管理系统/图书个性化推荐与实现系统

软件工程期末大作业,图书管理系统,包含ER图、程序流程图、属性图、结构图

2401_82857325的博客 3649

多线程,生产者和消费者

/**  * 注意:提交答案前一定仔细阅读“代码提交要求”,没有按照规则提交可能得不到技术分。 题目:编写一个多线程程序,模拟2个生产者生产产品,3个消费者消费产品。2个生产者不停的生产商品3个消费者不停的消费产品。 上传代码的时候将运算结果截图一起提交。  * @author Administrator  *两个生产者,3个消费者,同样的操作一种数据,而且必须是产品大于0才可以  *

yuminyan的专栏 605

【LPDDR4 - 学习二】LPDDR4 介绍 ——LPDDR4 芯片引脚说明解析

本文系统解析了LPDDR4内存芯片的引脚定义与特性,重点介绍了272球POPFBGA封装的双通道架构。内容涵盖电源管理(三级供电架构与上电时序)、控制信号(差分时钟与复用命令总线)、数据接口(16位双向数据总线与选通信号)以及校准复位等核心模块。通过表格详细列明了各引脚电压范围、功能定义及工程注意事项,并附有典型封装球位分布图。全文基于JEDEC标准,为移动设备内存设计提供全面的硬件参考,特别强调电源时序控制、信号完整性及抗干扰设计等关键点。

zap15622077817的博客 2641

2.STM32F407ZGT6 学习笔记-移植 FreeRTOS

1. 在工程下建议FreeRTOS文件夹 2. 在FreeRTOS文件夹下建立 src 和 port 文件夹 (src用于存放freertos源码,port文件夹存放内存和接口相关的文件) 3. 复制freertos/source文件夹下所有c文件复制到刚刚建立的freertos/src目录下 4. 复制FreeRTOSv9.0.0\FreeRTOS\Source\portablex下的MemMang和RVDS文件夹复制到刚刚建立的port问价夹下 5. 将FreeRTOSv9.0.0\FreeRTOS

Car12 1233

多线程——生产者和消费者模式

生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。 改问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。 生产者的主要作用是生成一定的数据放到缓冲区中,然后重复此过程;消费者也在缓冲区消耗这些数据。 该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会再缓冲区空时消耗数据。 任务说明: 创建一个共享区,共享区的容...

zZZxiaozhi的博客 430

2025年7月12日全国青少年信息素养大赛图形化(Scratch)编程小学低年级组复赛真题+答案解析

2025年7月12日全国青少年信息素养大赛图形化(Scratch)编程小学低年级组复赛真题+答案解析

伶俐角少儿编程 711

【多线程(三)】生产者和消费者模式

详细介绍了生产者和消费者模式,并用具体的例子帮助读者理解这种模式,也介绍了阻塞队列的基本使用,以及阻塞队列实现等待唤醒机制并分析了出现的问题。

hihielite的博客 1009

Open3D 体素下采样【2026最新版】

体素滤波,博客长期更新,本文最近更新时间为:2026年4月11日。

点云侠的博客 37万+

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Python——多线程-生产者和消费者模式

模式说明: ■ 生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。 ■ 该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。 ■ 生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。 ■ 消费者也在缓冲区消耗这些数据。 ■ 该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不回在缓冲区中空时消耗数据。 设...

weixin_45451726的博客 2252

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

二 多线程消费者和生产者模型

线程消费者和生产者模型 概述:生产者和消费者模型是多线程中的经典模型。在这里我想详细的介绍下关于该模型实现的多种方式。 生产者:数据产生的源头。 消费者:数据流向的结点。 对于该模型,感觉好熟悉。如RPC框架Dubbo就是有生产者和消费者之说,也就是服务提供者和服务消费者接口。对于消息队列也是如此。但是比如Dubbo来说,服务消费者接口是通过注册中心去调用服务的生产者的。而不是直接根据地址调用。...

大佛拈花的博客 330

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Java多线程生产者和消费者实现

一、概述 首先,我们需要明白生产者和消费者模型是为了解决多线程之间通信而产生的。其次,需要了解实现线程间通信用到了哪些知识点。先来看一张生产者和消费者模型图: 这里有四个对象,一个是生产者,一个是消费者,一个是容器,最后还有一个是需要生产的商品,虽然在图上没有体现出来。刚开始容器里面没有商品,消费者等待,生产者开始生产,当容器里面有商品了,生产者通知消费者去消费,如果生产的速度比较快,容器...

不将就 655

多线程生产者和消费者代码

import java.io.*; import java.text.SimpleDateFormat; import java.util.*; import java.lang.Object; public class jaChu { public static void main(String[] args) { //创建一个集合 List list=new ArrayList(); //创建生产者线程和消费者线程 Thread

weixin_48586922的博客 178

多线程-生产者和消费者模式

多线程是多任务处理的一种特殊形式,多线程处理允许让一个进程中同时运行两个或两个以上的线程。这样的话,能更加充分发挥计算机的性能,并高效完成用户的任务。第一步:加入头文件 第二步:子线程的实现 第三步:创建线程 join和detach的对比: join()函数是一个等待线程完成函数,主线程需要等待子线程运行结束了才可以结束 detach()函数是子线程的分离函数,当调用该函数后,线程就被分离到后台运行,主线程不需要等待该线程结束才结束 上面代码的运行结果:显示打印hello thread,然后等待1秒后,在打

qq_42178122的博客 1711

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

java多线程-生产者和消费者模式 方法 利用 生产者和消费者,共享一个 空间, 生产者 生产 的放进这个空间, 而消费者等待 生产者 生产并放入空间,然后再进入获取 而 这个空间,可以称之为 缓冲区 下面是例子,可以进行复习 package com.demo.practice; /** * @version : 1.0 * @auther : Firewine * @Program Na...

Firewine 的博客 178

Python 多线程和多进程的生产者消费者模型

任务 生产者负责生产数据(随机生成一个数字),消费者负责处理数据(判断生产出来的数据是不是质数)。 现在假设有一个生产者和多个消费者。 1. 多线程(Thread)的生产者消费者模型 import random import time import math import threading from queue import Queue class Producer(threading.Thread): # 生产者线程 def __init__(self, data, num_sum):

晋图的非正常人类胡言乱语集合 1590

java多线程生产者和消费者问题

java多线程生产者和消费者问题 描述 有一个车库,大小为5,当车库满了的时候,生产者不能再往里生产,当车库空了的时候生产者不能再买车。当有生产者往里放车的时候消费者不能买车,当消费者买车的时候,生产者不能生产车。 public class test1{ public static void main(String[] args) throws Exception { Car car=n...

qq_44170340的博客 170

java多线程——生产者和消费者

使用同步方法来保证数据的一致性,使用wait() 和 notify() 、notifyAll()方法来解决重复操作。 public class Test { public static void main(String[] args) { Message msg = new Message(); Producer producer = new Prod...

IT界的小清流 218

Java多线程模拟生产者和消费者模式

Java多线程模拟生产者和消费者模式 很久没有更新了,我又回来啦,因为之前也是蛮忙的,线程还是很有意思的,并且也是很重要,所以我就把这个有意思的案例分享粗来! 1.需求: 仓库采用list集合 仓库只能存储一个元素,一个元素就表示存满了 集合中元素个数为0,就表明仓库空了 保证List集合中永远最多只能存储一个元素 创建生产线程 Producer public class Producer...

qq_40733064的博客 733
上一篇: DecimalFormat的几种用法
下一篇: 大型ORACLE数据库优化设计方案
lb8607
博客等级 码龄18年 17粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值