NIO三大组件和ByteBuffer

news2024/12/28 12:06:22

目录

一、NIO三大组件

1、Channel

2、Buffer

3、Selector

二、ByteBuffer

1、基本使用

2、内部结构

3、常用方法

allocate方法

读取方法

字符串与ByteBuffer互转

Scattering Reads

4、念包、半包问题

三、文件编程

1、FileChannel

2、两个Channel传输数据

3、Path

4、Files


一、NIO三大组件

non-blocking io 非阻塞IO

1、Channel

Channel就是通道,在这里是指数据的双向通道,可以从channel将数据读入buffer,也可以将buffer的数据写入channel,而之前的stream要么是输入,要么是输出,channel比stream更底层

常见的Channel有:

  • FileChannel:做文件的数据传输通道
  • DatagramChannel:UDP传输的数据通道
  • SocketChannel:是做TCP的时候的数据传输通道(客户端服务器都能用)
  • ServerSocketChannel:是做TCP的时候的数据传输通道(专用服务器)

2、Buffer

buffer则用来缓冲读写数据,常见的buffer有:

ByteBuffer(字节为单位缓存数据的)是抽象类,实现类有:

  • MapperByteBuffer
  • DirectByteBuffer
  • HeapByteBuffer

3、Selector

selector单从字面意思是选择器,需要结合服务器的设计演化来理解它的用途

服务器处理多个客户端的通信,每次来一个就为客户端创建一个线程为客户端提供服务,如果多个就开多个线程,每个线程专门管理一个连接,当连接数很多的时候,就不行了,因为线程会占用内存,每个线程都会占用内存,当1000个线程的时候就很大了,内存会撑不住。 但是cpu核数有限,所以线程上下文切换成本高,这种只适合连接数少的场景。

改进为线程池就可以限制线程数量了,但是这样会让socket工作在堵塞模式下,因为一个线程要管理多个socket连接,一个时间只能处理一个,其余会阻塞(线程一个时间只能处理一个socket,直到这个socket断开连接,才能退出,即使这个socket并没有读写请求也得在上面等),所以只适合短连接的场景。

二、ByteBuffer

1、基本使用

初始化一个大小为10字节缓冲区,然后循环取写入读取,channel就是个读取数据的通道,每次读出来的数据就存在buffer中,然后调用buffer中的api去获取数据

ByteBuffer正确使用姿势:

  1. 向buffer写入数据,例如调用channel.read(buffer)
  2. 调用flip()切换到读模式
  3. 从buffer读取数据,例如调用buffer.get()
  4. 调用clear()或compact()切换到写模式
  5. 重复1-4的步骤

2、内部结构

ByteBuffer有以下重要的属性

  • capacity 容量
  • position 读写指针,索引下标
  • limit 读写的限制,应该读多少字节写多少字节

写模式下,position是写入位置,limit等于容量,下图表示写入4个字节后的状态

filp动作发生后,position切换为读取位置,limit切换为读取限制(写的最后一个位置)

读取4个字节后,状态

发生clear动作后,状态从读模式切换到写模式

compact方法,是把为读完的部分向前压缩,然后切换至写模式

3、常用方法

allocate方法

ByteBuffer.allocate()方法可以传入参数,为ByteBuffer分配内存,是固定的,不可以动态调节,超过这个容量就会报错,netty对byteBuffer做了增强可以动态调整。

使用allocate方法初始化使用的是Java的堆内存(读写效率较低,会收到GC的影响,GC的标记整理和复制都可能会数据拷贝),用allocateDirect()方法初始化使用的是直接内存(读写效率较高,会少一次数据拷贝;分配内存的效率低,使用不当可能会内存泄漏

读取方法

rewind():可以重复的读取数据,本来按顺序读取一次就往后移动指针,但是rewind的源码会把指针直接移动到0重新读取。与rewind搭配使用的还有markreset方法,mark会记录当前的position位置,reset会将position重置到mark的位置,这两个就是为rewind做增强。

字符串与ByteBuffer互转

字符串转ByteBuffer

第一种是手动转化为二进制形式put进去;第二种是用charset提供的encode方法,他提供了很多编码格式,放进去之后会自动切换为读模式;第三种也是nio提供的warp方法来放进去,这种也是会切换为读模式 

ByteBuffer转字符串

切换到读模式之后,所以如果是第一种模式转的buffer要加flip方法先切换模式,然后用charset的decode方法区转化,返回的结果是个CharBuffer加toString转为字符串

Scattering Reads

分散读取数据onetwothree,使用下面方式读取可以将数据填充到多个buffer

4、念包、半包问题

解决办法:

我们写个方法来接收消息,先切换为读模式,然后循环遍历到分隔符就截取出消息的长度,然后把消息存入心得byteBuffer中(循环从source去读往target去写)。

三、文件编程

1、FileChannel

FileChannel只能工作在阻塞模式下

获取

不能直接打开FileChannel,必须通过FileInputStream、FileOutputStream或者RandomAccessFile来获取FileChannel,它们都有getChannel方法

  • 通过FileInputStream获取channel只能读
  • 通过FileOutputStream获取的channel只能写
  • 通过RandomAccessFile是否能读写根据构造RandomAccessFile时的读写模式决定

读取

会从channel读取数据填充到ByteBuffer,返回值表示读了多少字节,-1表示到达文件末尾

int readBytes = channel.read(buffer);

写入

在while中调用channel.write是因为write方法并不能保证一次性将buffer中的内容全部写入channel,所以要循环判断有没有。 

关闭

channel必须关闭,不过调用了FileInputStream的close方法也会间接的调用channel的close方法

强制写入

操作系统出于性能考虑,会将数据缓存,当最终channel关闭的时候才会将这些数据同步到磁盘,不是立刻写入磁盘,可以调用force(true)方法将文件内容和元数据立刻写入磁盘

2、两个Channel传输数据

transferTo方法,就是将一个channel的数据传输到另一个channel上,第一个参数就是启始位置,第二个参数就是传输数据的大小,第三个参数就是目标位置。

用这种方式的效率会比输出流去写效率要高(操作系统底层的零拷贝进行优化)

传输的数据大小是有限制的2g,所以我们一次可能传输不完,要改进一下:

 这样就可以多次传输大于2g的数据了

3、Path

jdk7引入了Path和Paths类

  • Path用来表示文件路径
  • Paths是工具类,用来获取Path实例

  •   . 代表了当前路径
  •  .. 代表上一级路径

4、Files

也是1.7新增的类,检查文件是否存在

 

 

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

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

相关文章

解决 pyecharts 地图不显示的问题

总结 在 pyecharts 中如果修改了 online host,会导致绘制的地图显示不全,需要将 host 改回默认的 https://assets.pyecharts.org/assets/ 细节 最近需要使用 pyecharts 绘制中国地图,按官网的示例代码https://github.com/pyecharts/pyecha…

LLM - ChatGLM-6B (General Language Model) 的工程配置

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/131104546 Paper:GLM: General Language Model Pretraining with Autoregressive Blank Infilling ChatGLM是通用的预训练语…

Tower 10:Mac平台Git客户端软件

Tower是一款Mac OS X系统上的Git客户端软件,它提供了丰富的功能和工具,帮助用户更加方便地管理和使用Git版本控制系统。 以下是Tower的一些特点: 1. 界面友好:Tower的界面友好,使用户能够轻松地掌握软件的使用方法。 …

数据库表结构设计---多表

这里写目录标题 多表设计一对多简介物理外键需求分析sql语句添加物理外键idea图形化工具设置外键 一对一多对多二级目录二级目录 多表设计 一对多 简介 一个表的某个字段,对应一个表 父表 子表 物理外键 需求分析 sql语句添加物理外键 设置物理外键的sql语句 为…

【强化学习】常用算法之一 “SAC”

作者主页:爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

Ameya360:广和通发布新一代5G FWA解决方案

为满足日益增长的5G宽带连接需求,提升FWA部署的经济效益和技术可行性,广和通在MWCS 2023期间发布了基于新一代5G模组FG190&FG180的5G FWA整体解决方案,为FWA等移动终端提供了灵活、便捷、高效、可靠的联网方案,促进FWA快速迭代…

SC2161旋变数字转换器可pin对pin兼容AD2S1210

SC2161 是一款 10 位至 16 位分辨率旋变数字转换器,集成片上可编程正弦波振荡器,为旋变器提供正弦波激励。可pin对pin兼容AD2S1210。 转换器的正弦和余弦输入端允许输入 3.15 Vp−p 27%、频率为 2 kHz 至 20 kHz 范围内的信号。Type II 伺服环路用于跟踪…

基于51单片机的智能照明系统

目录 基于51单片机的智能照明系统一、原理图二、部分代码三、视频演示 基于51单片机的智能照明系统 功能: 1.通过LCD屏幕显示实时时间、光强和物体等 2.通过DS1302获取实时时间 3.通过按键调整灯的开关时间和手自动设置手动模式下手动开灯 4.蜂鸣器报警功能 5.上位…

“因构建 而可见”,亚马逊云科技中国峰会助力企业数字化转型升级

过去十年,数字化转型的浪潮携带着机遇和挑战席卷而来,几乎每个企业都在做数字化转型,开始向大数据、人工智能等新技术寻求生产力的突破。但随着数字化转型深入,很多企业开始感受到数字化投入的成本压力,加之新技术正带…

ML算法——Support Vector Machine随笔【机器学习】

文章目录 4、Support Vector Machine (SVM)4.1、理论部分4.1.1、更优的决策边界4.1.2、解决低维不可分问题 4.2、sklearn 实现4.2.1、SVM 分类(SVC)4.2.2、SVM回归(SVR)4.2.3、网格调参 4.3、案例 4、Support Vector Machine (SVM…

用Java编写Groovy脚本,然后用命令行执行该脚本

1、Groovy 语言简介 Groovy 是 Apache 旗下的一门基于 JVM 平台的动态/敏捷编程语言Groovy 可以与 Java 语言无缝对接,在写 Groovy 的时候如果忘记了语法可以直接按Java的语法继续写,也可以在 Java 中调用 Groovy 脚本,都可以很好的工作Groo…

Pytorch常用的函数(三)深度学习中常见的卷积操作详细总结

Pytorch常用的函数(三)深度学习中常见的卷积操作 1、标准卷积(Standard Convolution) 1.1 标准卷积的理解 我们直接来看二维卷积,这在实际应用中是最常见的。 上图中Conv 2D其实就是卷积核,也叫做滤波器。滤波器的值决定了输出的情况,模型…

【Java】Java核心 86:Git 教程(9)GIT远程仓库操作

文章目录 14.GIT远程仓库操作-关联、拉取、推送、克隆目标内容小结 Git提供了一系列命令来进行远程仓库的操作。 下面是一些常用的Git远程仓库操作&#xff1a; 克隆远程仓库到本地&#xff1a; git clone <远程仓库URL>查看远程仓库信息&#xff1a; git remote -v添…

功能键F4在Microsoft Excel中有什么用

的确,许多 Excel 用户发现使用键盘快捷键对他们来说更有效。事实上,键盘快捷键可能是使用鼠标的最佳选择,因为使用 Excel 时使用触摸屏可能不是视力障碍者的最佳选择。 使用功能键,如 Excel 中的 F4 以及 F2 可能是非常必要的。在这篇文章中,我们将研究功能键 F4 及其在 …

【Java】Java核心 85:Git 教程(8)GIT远程仓库介绍与码云仓库注册创建

文章目录 13.GIT远程仓库介绍与码云仓库注册创建目标小结 Git是一个分布式版本控制系统&#xff0c;它允许多个开发者协同工作并管理代码的版本。远程仓库是存放在网络上的Git仓库&#xff0c;可以用于团队成员之间的代码共享和协作。 常见的远程仓库托管服务提供商有GitHub、…

XShell、XFtp、Linux上MySQL的远程连接及使用

下载资源包&#xff0c;请于文章顶部下载即可 XShell的使用 1. 打开安装好的XShell 2. 点击左上角新建连接 3. 填写相应连接服务器信息 4. 输入需要连接到Linux操作系统哪个用户的用户名 5. 输入连接到用户的密码 6. 远程登录Linux成功 7. 此时可以正常使用Linux指令操作Linu…

chatgpt赋能python:隐藏鼠标:Python实现隐藏鼠标的应用

隐藏鼠标&#xff1a;Python实现隐藏鼠标的应用 作为一名有10年Python编程经验的工程师&#xff0c;我深知Python在图形用户界面(GUI)开发上的优势&#xff0c;其中一个有趣而且有用的应用就是隐藏鼠标。 在某些情况下&#xff0c;用户可能希望隐藏鼠标&#xff0c;这可以用于…

ARM-异常与中断(四)

文章目录 中断中断请求、中断源中断服务程序保存现场、恢复现场中断仲裁、中断优先级中断嵌套 异常广义上的异常同步异常异步异常精确异步异常&#xff08;Precise Asynchronous Exception&#xff09;非精确异步异常&#xff08;Imprecise Asynchronous Exception&#xff09;…

【DBA专属】MHA高可用数据库集群-----------一主一备两从一管理,一个VIP客户端

MHA高可用数据库集群 目录 环境配置&#xff1a; 所有操作系统均为centos 7.x 64bit 1、关闭防火墙&#xff1a;&#xff08;所有服务器&#xff09; 2.配置所有主机名映射&#xff08;所有服务器&#xff09; 3、同步时区 4.安装MHA node及相关perl依赖包&#xff08;所有…

AutoSAR系列讲解(入门篇)4.1-BSW概述

BSW概述 一、什么是BSW 二、BSW的结构 1、微控制器硬件抽象层&#xff08;MCAL&#xff09; 2、ECU抽象层 3、服务层 4、复杂驱动 三、再将结构细分 一、什么是BSW 中文翻译就是基础软件层&#xff08;Basic Software&#xff09;。这个基础软件层实质上就是将整个ECU分…