java实现生产者和消费者问题的几种方式

计算机组成原理实验(已通关)-华中科技大学头歌Educoder(Logisim) 汉字国标码转区位码实验 汉字机内码获取实验 8位可控加减法电路设计 第2关 CLA182四位先行进位电路设计 第3关 4位快速加法器设计 第4关 16位快速加法器设计 第5关 32位快速加法器设计 第6关 5位无符号阵列乘法器设计 6位有符号补码阵列乘法器 乘法流水线设计 原码一位乘法器设计 偶校验编码设计 偶校验解码电路设计 16位海明编码电路设计 16位海明解码电路设计 海明编码流水传输实验 16位CRC并行编解码电路设计 CRC编码流水传输实验 阅读详情

一:使用syncronized

这是最直接原始的一种实现方式:

//数据源,用来模拟生产者生产的对象
public class DataSource {
    //数据源--每个元素都是时间类型
    private List<Date> data;
    //设置数据源大小
    private int maxSize;

    public DataSource() {
        this.data = new LinkedList<>();
        this.maxSize = 10;
    }
    //初始化数据源方法-set
    public synchronized void set(){
        //如果数据源中的数据达到最大值,则让其等待
        while (data.size()==maxSize){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        data.add(new Date());
        System.out.printf("Set: %d.\n",data.size());
        //在方法的尾部,调用notifyAll()方法来唤醒,所有在wait()方法上等待的线程
        notifyAll();
    }
    public synchronized void get(){
        //如果数据源中没有数据,则让其等待
        while (data.size()==0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("Get: %d: %s .\n",data.size(),((LinkedList<?>)data).poll());
    }
}
//生产者
public class Producer implements Runnable {
    private DataSource dataSource;

    public Producer(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            dataSource.set();
        }
    }
}
//消费者
public class Consumer implements Runnable {
    private DataSource dataSource;

    public Consumer(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            dataSource.get();
        }
    }
}
//测试类
public class Main {
    public static void main(String[] args) {
        DataSource dataSource = new DataSource();
        Thread producerThreads[] = new Thread[3];
        Thread consumerThreads[] = new Thread[4];
        for (int i = 0; i < 3; i++) producerThreads[i] = new Thread(new Producer(dataSource));
        for (int i = 0; i < 4; i++) consumerThreads[i] = new Thread(new Consumer(dataSource));
        for (int i = 0; i < 3; i++) producerThreads[i].start();
        for (int i = 0; i < 4; i++) consumerThreads[i].start();

    }
}

二:使用Lock和Condition

lock是实现java同步的另外一种方式,使用lock比syncronized更加灵活。一个锁可能伴随着多个条件,这些条件在condition接口中。
我们将上面代码中DataSource类修改一下:

 //数据源--每个元素都是时间类型
    private List<Date> data;
    //设置数据源大小
    private int maxSize;
    private Condition add;
    private Condition sub;
    private Lock lock;

    public DataSource() {
        this.data = new LinkedList<>();
        this.maxSize = 10;
        lock = new ReentrantLock();
        add = lock.newCondition();
        sub = lock.newCondition();
    }
    //初始化数据源方法-set
    public void set(){
        //获取锁
        lock.lock();
        try{
            //如果数据源中的数据达到最大值,则让其等待
            while (data.size()==maxSize){
            //注意,这里是await,wait()和notify()必须在synchronized的代码块中使用 因为只有在获取当前对象的锁时才能进行这两个操作 否则会报异常 而await()和signal()一般与Lock()配合使用
                add.await();
            }
            data.add(new Date());
            System.out.printf("Set: %d,%s.\n",data.size(),Thread.currentThread().getName());
            //在方法的尾部,signalAll()方法来唤醒,所有在wait()方法上等待的线程
            sub.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //释放锁
            lock.unlock();
        }

    }
    public void get(){
        lock.lock();
        //如果数据源中没有数据,则让其等待
        try {
            while (data.size()==0){
                sub.await();
            }
            add.signalAll();
            System.out.printf("Get: %d: %s .\n",data.size(),((LinkedList<?>)data).poll());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

三:使用Exchanger 类

Exchanger 类允许2个并发任务互相交换数据。Exchanger 定义了一个同步点,当两个线程到达这个点后,他们互相交换数据。也就是说,使用第一个线程的数据类型变成第二个的,然后第二个线程的数据类型变成第一个的。
只是Exchanger只能操作两个线程,所以只能在生产者和消费者中各选择一个来实现这个类。

public class Producer implements Runnable {
    private List<String> buffer;
    //Producer 中包含 exchanger实例
    private final Exchanger<List<String>> exchanger ;

    public Producer(List<String> buffer, Exchanger<List<String>> exchanger) {
        this.buffer = buffer;
        this.exchanger = exchanger;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                String message = "Event "+((i*10)+j);
                System.out.printf("Product : %s .\n",message);
                buffer.add(message);
            }
            try {
            //设置交换点
                buffer = exchanger.exchange(buffer);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("Producer : %d \n",buffer.size());
        }
    }
}
public class Consumer implements Runnable {
    private List<String> buffer;
    private final Exchanger<List<String>> exchanger;

    public Consumer(List<String> buffer, Exchanger<List<String>> exchanger) {
        this.buffer = buffer;
        this.exchanger = exchanger;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                buffer = exchanger.exchange(buffer);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int j = 0; j < 10; j++) {
                String message = buffer.get(0);
                System.out.printf("Consumer : %s .\n",message);
                buffer.remove(0);
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        List<String> buffer1 = new ArrayList<>();
        List<String> buffer2 = new ArrayList<>();
        Exchanger<List<String>> exchanger = new Exchanger<>();
        Producer producer = new Producer(buffer1, exchanger);
        Consumer consumer = new Consumer(buffer2, exchanger);
        Thread threadProducer = new Thread(producer);
        Thread threadConsumer = new Thread(consumer);
        threadProducer.start();
        threadConsumer.start();


    }
}
Visual Studio Installer下载失败的5种修复方法(含DNS修改/补丁安装) 本文针对Visual Studio Installer下载安装文件失败的问题,提供了从网络层到系统层的深度排查与修复指南。详细介绍了DNS修改、代理配置、防火墙设置、系统服务检查等5种核心修复方法,并包含离线安装与手动补丁等替代方案,帮助开发者彻底解决安装难题。 阅读详情

相关推荐

YOLOv11+SAHI实战:5步搞定无人机航拍小目标检测(附VisDrone数据集调参技巧)

本文详细介绍了如何结合YOLOv11目标检测框架与SAHI切片推理技术,高效解决无人机航拍图像中的小目标检测难题。通过VisDrone数据集调参技巧和5步实战指南,帮助开发者快速构建高性能检测系统,显著提升小目标检测的准确率和效率。

rum55的博客 191

JUC - 多线程之Synchronized和Lock锁;生产者消费者模式(一)

JUC首先,再简单说一下并行、并发;进程、线程。

MinggeQingchun的博客 731

similarity network fusion for aggregating data types on a genomic scale

基因组规模上的聚合数据类型的相似性网络融合 摘要:         近期的技术已经使收集不同类型的全基因组数据十分划算,结合这些数据去创建一个给定的疾病或生物过程的一个全面视图的计算方法是有必要的。相似网络融合(SNF:similarity network fusion)通过创建每一个可利用的数据类型的样本(如,患者)的网络可以解决这个问题。例如,创建一个给定一群患者疾病的全面视图,SNF计算

augustar学习笔记 7870

Java 生产者和消费者 5种实现方式

Java 生产者和消费者 4种实现方式1 Objcet 的 wait() 和 notifyAll()2 1 Objcet 的 wait() 和 notifyAll() package com.xu.thread; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * @author Administrator */ public class

风信子 3245

华为ENSP完整安装教程

华为ENSP完整安装教程

Hnm456756的博客 7340

模型优化系列——模型剪枝/量化概述

模型优化目的:通过减少模型大小,提高推理速度等使模型成功部署在各个硬件中并实时有效运作。

qq_61210574的博客 1293

Java多种方式解决生产者消费者问题(十分详细)

生产者消费者问题 一、问题描述 生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。生产者生成一定量的数据放到缓冲区中,然后重复此过程;与此同时,消费者也在缓冲区消耗这些数据。生产者和消费者之间必须保持同步,要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区空时消耗...

爱你の大表哥的博客 6万+

Linux(31)Rockchip RK3568 Ubuntu22.04上部署 Docker: 问题与解决方案

本博客在总结这些问题及其解决方案,为遇到类似问题的兄弟提供参考,如果我后续有碰到其他Docker 问题也会在此更新补充。

我其实什么都不会 1646

Java语言synchronized与lock实现生产者消费者

这个配合生产者,消费者问题来看最适合不过了,上代码package test;import java.util.LinkedList; import java.util.Queue; import java.util.Random;public class ProducerConsumer { public static void main(String args[]) { Q

dahongwudi的专栏 681

C#上位机通信层封装:西门子S7NetPlus库的优雅使用

支持S7-1200/1500(机架号0,槽号1)、S7-300/400(机架号/槽号需根据实际配置);支持位(Bit)、字节(Byte)、字(Word)、双字(DWord)、浮点数(Float/Double)等数据类型的读写;支持DB块、输入寄存器(I)、输出寄存器(Q)、内存寄存器(M)、定时器(T)、计数器(C)的操作;轻量无依赖,兼容.NET 5+。首先定义核心枚举和常量,统一规范参数类型,避免硬编码。/// 西门子PLC型号(对应不同的机架/槽号默认配置)

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1085

TOGAF架构内容—TOGAF 内容框架和企业元模型

TOGAF架构内容—TOGAF 内容框架和企业元模型

深圳市多克创新科技有限公司 1664

synchronized和ReentrantLock实现消费者生产者问题

并发执行和并行执行的区别:并行执行是指两个或多个事件在同一时刻发生,而并发执行是指两个或多个事情在同一时间间隔内发生。并发执行在宏观层面上看,事情之间是同时发生的。比如说在2秒的时间内发生的两件事情,在历史的角度上可以看作是“同时发生”的。 在Java中,多个线程对临界区资源操作时,需要保持程序的可再现性,或者说内存可见性。不管哪个线程操作了临界资源,操作的结果都应该对下一个操作该资源的线程可见

做最好的自己,遇见最美好的你 852

【ROS2】RViz2加载URDF模型文件

1)运行RViz2rviz22)添加组件:RobotModel3)选择通过文件添加4)选择URDF文件,此时会报错,需要修改Fixed Frame为map即可

郭老二 1450

java两个生产两个消费模式_java实现生产者和消费者问题的几种方式

展开全部生产者消费者问题是多线程的一个经典问题,它描述是有一块缓冲区作为仓库,生产者可以将产品放62616964757a686964616fe58685e5aeb931333366303131入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类:采用某种机制保护生产者和消费者之间的同步;在生产者和消费者之间建立一个管道。第一种方式有较高的效率,并且易于实现,代码的可控制性较...

weixin_39998273的博客 416

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

生产者消费者模式,以及基于BlockingQueue的快速实现

什么是生产者消费者模式?简单来说就是有两个角色,一个角色主要负责生产数据,一个角色主要负责消费(使用)数据。那么生产者直接依赖消费者,然后直接调用是否可以?答案是可以的,但是有些场景无法及时解决,典型的就是生产者消费者的速度无法同步,导致整体的速度上不去的情况。执行速度永远取决于二者的最小速度(假设生产者和消费者的速度时快时慢)。一般的解决方案是什么呢?我们通常会加一个中间件,作为缓冲队列。 生...

weixin_40229012的博客 269

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

生产者和消费者代码———操作系统_「面试必备」手撕代码,你怕不怕?

Part 1.生产者-消费者问题这绝对是属于重点了,不管是考察对于该重要模型的理解还是考察代码能力,这都是一道很好的考题,所以很有必要的,我们先来回顾一下什么是生产者-消费者问题;问题简单回顾如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互...

weixin_39915500的博客 297

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

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

java生产者消费者代码_【面试必备】手撕代码,你怕不怕?

Part 1.生产者-消费者问题这绝对是属于重点了,不管是考察对于该重要模型的理解还是考察代码能力,这都是一道很好的考题,所以很有必要的,我们先来回顾一下什么是生产者-消费者问题;问题简单回顾如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互...

weixin_39598584的博客 228

java多线程的几种实现方式

/比第一种多出这步(new一个Thread类,并将任务类r传进去)1.定义一个Mythread类并继承Thread类,重写Thread的run方法,方法内部写具体的业务代码。//第二种实现runable接口,重写Runable接口run方法。// 多线程的第一种启动方式继承Thread,成为子类。2.调用Mythread类。1.定义MyRun类。

qq_36633637的博客 600

生产者/消费者问题的多种Java实现方式

生产者/消费者问题的多种Java实现方式

愤怒的小狐狸----博客专栏 13万+

Java实现生产者消费者问题

生产者-消费者问题是计算机科学中经典的同步问题之一,它描述了多个线程在共享数据的情况下如何协同工作。该问题通常涉及到一个共享缓冲区,其中生产者线程生成数据并将其放入缓冲区,而消费者线程从缓冲区中取出数据并对其进行处理。生产者和消费者线程必须协同工作,以避免竞态条件和死锁等问题。以上为通过Java代码实现解决生产消费者问题的实例,通过本实例希望大家能学会如果解决此问题,学会如何数据共享时,各个线程协同工作。

无简介 6121

Java可视化实现生产者消费者问题

引言:生产者消费者问题是一个十分经典的多线程问题。为了更加形象地描述这个问题,采用可视化的形式展示此过程。

王小明爱吃大菠萝的博客 6082

Java生产者消费者的五种实现方式

前言生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。 现在用四种方式来实现生产者消费者模型

zgj12138的博客 4682

【转】-Java实现生产者和消费者的5种方式

生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,生产者往存储空间中添加产品,消费者从存储空间中取走产品,当存储空间为空时,消费者阻塞,当存储空间满时,生产者阻塞。现在用四种方式来实现生产者消费者模型。

booleandev 1963

java实现生产者消费者模式

一: 什么是生产者消费者模型 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。 简单来说: 生产者消费者模型就是指,在一个系统中,存在两种角色,一个为生产者,一个为消费者,通过一个缓冲区(仓库)进行通信,生产者将生产的产品放入仓库,消费...

向上的"狼"的博客 8207

生产者消费者模式的几种实现方式以及线程安全问题

生产者消费者模式的几种实现方式拿我们生活中的例子来说,工厂生产出来的产品总是要输出到外面使用的,这就是生产与消费的概念。 在我们实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。 产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。 第一种:采用wait—notify实现生产者消费者

noaman_wgs的博客 1万+

java实现生产者和消费者

本篇博文主要介绍如何使用java来实现简单的生产者和消费者 来帮助大家简单的入门理解生产者和消费者模式 一、对生产者消费者的理解 生产者消费者模式是并发、多线程编程中经典的设计模式。 简单来看,就是一个类负责生产,一个类负责消费。举例来说,一个变量,生产者不断增加这个变量,消费者不断减少这个变量。在互联网应用中,抢票机制就是应用了该模式,比如大麦网演唱会门票抢票,12306火车票抢票等。

fallwind_of_july的博客 1万+
上一篇: 一道面试题的拓展
下一篇: 线程的生命周期
最伤离别
博客等级 码龄15年 15粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值