【Java】进程通信(共享内存)

news2024/12/24 22:03:36

🎈博客主页:🌈我的主页🌈
🎈欢迎点赞 👍 收藏 🌟留言 📝 欢迎讨论!👏
🎈本文由 【泠青沼~】 原创,首发于 CSDN🚩🚩🚩
🎈由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!🌠个人主页


目录

  • 🌟 一、核心要点
    • 🌟🌟 1.1、MappedByteBuffer
    • 🌟🌟1.2、 FileChannel
    • 🌟🌟1.3、 RandomAccessFile
  • 🌟 二、Java类的实现
    • 🌟🌟 2.1、写进程(加锁)
    • 🌟🌟 2.2、读进程(加锁)
    • 🌟🌟 2.3、运行读写进程
    • 🌟🌟 2.4、写进程(不加锁)
    • 🌟🌟 2.4、读进程(不加锁)


🌟 一、核心要点

🌟🌟 1.1、MappedByteBuffer

Java IO 操作的BufferedReaderBufferedInputStream 等相信大家都很熟悉,不过在 Java NIO 中引入了一种基于MappedByteBuffer操作大文件的方式,其读写性能极高。

MappedByteBuffer 为共享内存缓冲区,实际上是一个磁盘文件的内存映射,实现内存与文件的同步变化,可有效地保证共享内存的实现。

🌟🌟1.2、 FileChannel

FileChannel 是将共享内存和磁盘文件建立联系的文件通道类。FileChannel 类的加入是JDK为了统一对外设备(文件、网络接口等)的访问方法,并加强了多线程对同一文件进行存取的安全性。我们在这里用它来建立共享内存和磁盘文件间的一个通道。

🌟🌟1.3、 RandomAccessFile

RandomAccessFileJava IO体系中功能最丰富的文件内容访问类,它提供很多方法来操作文件,包括读写支持,与普通的IO流相比,它最大的特别之处就是支持任意访问的方式,程序可以直接跳到任意地方来读写数据。

举个例子:

如果我们要向已存在的大小为 1G 的 txt 文本里末尾追加一行文字,内容如下“ 你好,我是小明”。其实直接使用Java 中的流读取 txt 文本里所有的数据转成字符串后,然后拼接“你好,我是小明”,又写回文本即可。
但如果需求改了,我们要想向大小为 8G 的 txt 文本里追加数据。如果我们电脑的内存只有 4G ,强制读取所有的数据并追加,将会报内存溢出的异常。显然,上面的方法不再合适。
如果我们使用 JAVA IO 体系中的 RandomAccessFile类来完成的话,可以实现零内存追加。其实,这就是支持任意位置读写类的强大之处。

🌟 二、Java类的实现

🌟🌟 2.1、写进程(加锁)

/**
 * create by dong on 2023/5/8
 */
public class NIOWriteLock {
    private static RandomAccessFile raf;
    public static void main(String[] args) throws Exception {
        //获取随机存取文件对象,建立文件和内存的映射,即时双向同步
        raf = new RandomAccessFile("E:/temp/source.dat", "rw");
        FileChannel fc = raf.getChannel();      //获取文件通道
        MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, 1024);  //获取共享内存缓冲区
        FileLock flock=null;

        for(int i=65;i<91;i++){
            //阻塞独占锁,当文件锁不可用时,当前进程会被挂起
            flock=fc.lock();
            System.out.println(System.currentTimeMillis() +  ":write:" + (char)i);
            mbb.put(i-65,(byte)i);  //从文件第一个字节位置开始写入数据
            flock.release();        //释放锁
            Thread.sleep(1000);
        }
    }
}

🌟🌟 2.2、读进程(加锁)

public class NIOReadLock {
    private static RandomAccessFile raf;

    public static void main(String[] args) throws Exception {

        raf = new RandomAccessFile("D:/tmp/data.dat", "rw");
        FileChannel fc = raf.getChannel();
        MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, 1024);
        FileLock flock=null;

        for(int i=0;i<26;i++){
            flock=fc.lock();    //上锁
            System.out.println( System.currentTimeMillis() +  ":read:" + (char)mbb.get(i));
            flock.release();    //释放锁
            Thread.sleep(1000);
        }
    }
}

🌟🌟 2.3、运行读写进程

因为我们采用了文件锁方式来规范读写操作,该方法在读操作和写操作之前都采用加锁来保证数据安全。
在这里插入图片描述
在这里插入图片描述

🌟🌟 2.4、写进程(不加锁)

public class NIOWrite {

    private static RandomAccessFile raf;
    public static void main(String[] args) throws Exception {
        //建立文件和内存的映射,即时双向同步
        raf = new RandomAccessFile("D:/tmp/data.dat", "rw");
        FileChannel fc = raf.getChannel();
        MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, 1024);

        //清除文件内容 ,对 MappedByteBuffer 的操作就是对文件的操作
        for(int i=0;i<1024;i++){
            mbb.put(i,(byte)0);
        }

        //从文件的第二个字节开始,依次写入 A-Z 字母,第一个字节指明当前操作的位置
        for(int i=65;i<91;i++){
            int index = i-63;
            int flag = mbb.get(0);  //可读标置第一个字节为 0
            if(flag != 0){          //不是可写标示 0,则重复循环,等待
                i--;
                continue;
            }
            mbb.put(0,(byte)1);         //正在写数据,标志第一个字节为 1
            mbb.put(1,(byte)(index));   //文件第二个字节说明,写数据的位置

            System.out.println(System.currentTimeMillis() +  ":position:" + index +"write:" + (char)i);

            mbb.put(index,(byte)i);     //index 位置写入数据
            mbb.put(0,(byte)2);         //置可读数据标志第一个字节为 2

            Thread.sleep(3000);
        }
    }
}

🌟🌟 2.4、读进程(不加锁)

public class NIORead {
    private static RandomAccessFile raf;

    public static void main(String[] args) throws Exception {

        raf = new RandomAccessFile("D:/tmp/data.dat", "rw");
        FileChannel fc = raf.getChannel();
        MappedByteBuffer mbb = fc.map(MapMode.READ_WRITE, 0, 1024);
        int lastIndex = 0;

        for(int i=1;i<27;i++){
            int flag = mbb.get(0);      //取读写数据的标志    
            int index = mbb.get(1);     //读取数据的位置,2为可读    

            if(flag != 2 || index == lastIndex){ //假如不可读,或未写入新数据时重复循环    
                i--;
                continue;
            }

            lastIndex = index;
            System.out.println( System.currentTimeMillis() +  ":position:" + index +"read:" + (char)mbb.get(index));

            mbb.put(0,(byte)0);     //置第一个字节为可读标志为 0    

            if(index == 27){        //读完数据后退出    
                break;
            }
        }
    }
}  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/504779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyQt5桌面应用开发(12):QFile与线程安全

本文目录 PyQt5桌面应用系列segment faultgdb backtraceopen & readQFile总结 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQt5桌面应用开发&#xff08;2&#xff09;&#xff1a;事件循环 PyQt5桌面应用开发&#xff08;3&…

怎么恢复回收站?分享4个宝藏方法!

案例&#xff1a;怎么恢复回收站 【请问大家怎么恢复误删的文件呀&#xff1f;如果回收站被清空了&#xff0c;又应该怎么恢复呢&#xff1f;】 电脑回收站是我们存储被删除文件的地方。但是有时候&#xff0c;我们会不小心把一些重要的文件或者照片误删了。这时候&#xff0…

LED驱动程序框架

1. 字符设备驱动程序框架 2. 基于分层思想的LED驱动 2.1 把驱动拆分为通用的框架和具体的硬件操作 把驱动拆分为通用的框架(leddrv.c)、具体的硬件操作(board_X.c)&#xff1a; 如图&#xff1a; 以面向对象的思想&#xff0c;改进代码 抽象出一个结构体&#xff1a; 每个…

数据库管理-第七十三期 最近(20230509)

数据库管理 2023-05-09 第七十三期 最近1 证书2 EMCC 13.5.0.143 破百总结 第七十三期 最近 五一前后&#xff0c;除了X8那台的故障以外&#xff0c;还是做了或者探索了一些其他的东西。 1 证书 在五一假期的最后一天&#xff0c;还是在家通过线上的方式通过了1Z0-902&#…

Springboot +Flowable,三种常见网关的使用(排他、并行、包容网关)(一)

一.简介 Flowable 中常用的网关主要有三种类型&#xff0c;分别是&#xff1a; 排他网关并行网关包容网关 下面来说下这三种的网关的概念和用法。 二.排他网关 排他网关&#xff0c;也叫互斥网关&#xff0c;截图如下&#xff1a; 排他网关有一个入口&#xff0c;多个有效…

亚马逊云科技发力医疗与生命科学行业,加速数字化创新

2023年4月27日&#xff0c;亚马逊云科技医疗与生命科学行业峰会召开&#xff0c;会议汇聚了业界专家和思想领袖&#xff0c;共同探讨行业数字化转型和创新之道。作为全球医疗及生命科学行业云计算引领者&#xff0c;亚马逊云科技将围绕数据、算力和行业用户体验三大需求发力&am…

MySQL百万数据深度分页优化思路分析

业务场景 一般在项目开发中会有很多的统计数据需要进行上报分析&#xff0c;一般在分析过后会在后台展示出来给运营和产品进行分页查看&#xff0c;最常见的一种就是根据日期进行筛选。这种统计数据随着时间的推移数据量会慢慢的变大&#xff0c;达到百万、千万条数据只是时间…

UWA发布 | Unity手游性能蓝皮书

最新2022年度Unity手游蓝皮书出炉&#xff01;此次发布分析了2022年1月至2023年3月期间&#xff0c;游戏行业使用Unity引擎进行手游开发过程中及游戏上线后的性能表现&#xff0c;从测试机型分布、引擎各模块开销、内存占用等方面进行汇总分析&#xff0c;反映了Unity手游行业的…

Flink dataStream,如何开窗,如何进行窗口内计算

目录 开窗方式 windowAll() window() 窗口类型 基于时间 基于数量 开窗后的处理函数 全量聚合函数&#xff08;也叫窗口函数&#xff09; 增量聚合函数 增量聚合函数携带一个全量聚合函数 开窗方式 windowAll() 对于没有keyBy的数据流 window() 对于KeyBy后的数据…

交工技术文档表格-SH3503-2001

(阀门试验记录)(管道补偿器安装记录)(管道组成件校验性检查记录)(SHA级管道管螺纹、密封面加工记录)(高压、SHA级管道弯管加工记录)(管道静电接地测试记录)管道系统安装检查与压力试验记录)管道系统泄露性与真空试验记录)(管道吹洗、清洗脱脂记录)(给排水压力管道强度及严密试验…

685页40万字某省市场监管智慧应用一体化项目(word可编辑)

1.2.3.1 数字XX公共能力建设现状 1.2.3.1.1 数字XX通用基础应用平台现状 通用基础应用平台提供具有共性特征的跨部门、跨层级业务应用&#xff0c;与本项目有关的平台包括某省网上办事大厅、某省政务服务 APP 统一平台&#xff08;X政通 APP&#xff09;、某省公共信用信息平…

一次SQL的完整处理流程

流程&#xff1a; 1. 客户端到连接器是通过TCP/IP SSL通信协议连接的&#xff0c; 2.连接器验证MySQL权限信息是否正常&#xff0c;连接量是否正常&#xff0c;长时间没有连接服务器会自动断开等等 &#xff1b; 3. 然后到解析器&#xff0c;通过客户端发过来的sql进行语法解析…

电力系统储能调峰、调频模型研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

FS2114恒流模式的PWM升压IC,内置过温、关断、欠压、过流保护

FS2114是升压DC-DC转换器。其内置0.2Ω功率MOSFET的PWM电路&#xff0c;使该稳压器具有高效率。内部补偿网络还可以程度地 减少了6个外部元件的数量。 0.6V精密基准电压&#xff0c;内部软启动功能可以减低浪涌电流。 FS2114采用SOT23-6L封装&#xff0c;为应用节省空 间PCB。…

手机录屏怎么操作?有哪些好用的方法

在现代科技的时代&#xff0c;手机录屏已经成为了常见的操作。这项技术允许我们在手机上录制视频并分享给他人。但是&#xff0c;很多人可能并不知道如何进行手机录屏。下面我们将介绍手机录屏的操作方法和一些值得推荐的工具。 手机录屏操作方法 对于iOS用户&#xff0c;可以…

Java设计模式-适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09;是一种常见的设计模式&#xff0c;它主要用于在不改变现有系统结构的情况下&#xff0c;将一个类的接口转换成客户端所期望的另一个接口。在本文中&#xff0c;我们将介绍适配器模式的基本概念、实现方法以及优缺点&#xff…

FS4056是一款完整的单节锂离子电池采用恒定电流/恒定电压线性充电器IC

FS4056是一款完整的单节锂离子电池采用恒定电流/恒定电压线性充电器IC。其底部带有散热片的 ESOP8/DIP8 封装与较少的外部元件数目使得 FS4056成为便携式应用的理想选择。FS4056可以适合 USB 电源和适配器电源工作。   由于采用了内部 PMOSFET 架构&#xff0c;加上防倒充电路…

CM201-1-YS_当贝纯净桌面-线刷固件包

CM201-1-YS_当贝纯净桌面-线刷固件包-内有教程 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&#xff1b; 4、大量精简内置的没用的软件&#xff0c;运行速度提…

连接型CRM助力医疗企业把“成本中心”变成“利润中心”

在市场竞争日益加剧的情形下&#xff0c;企业获客成本大幅上涨&#xff0c;存量客户的维护和开发开始被重视&#xff0c;售后服务部门的职责在企业中发挥的价值越来越大。因为企业售后服务不仅能帮助客户解决问题的部门&#xff0c;还是客户与企业沟通的桥梁&#xff0c;将客户…

Linux——进程间通信(System V共享内存)

目录 共享内存示意图(理解共享内存的关键) shmget函数 第一个参数 ftok函数 使用ftok打印key值 第二个参数 第三个参数 返回值 打印shmget 再谈key值 举例理解key值 共享内存的过程 创建共享内存 关联共享内存 去除关联 ​编辑 使用共享内存通信 删除共享内存…