NIO学习笔记

1 简介

Java NIO是从java 1.4版本开始引入的一个新的IO API

  • 目的—替代标准版的Java IO API

NIO与原来的IO有同样的作用和目的,但是使用方式完全不同

  • NIO支持面向缓冲区的,基于通道的操作
  • NIO以更高效的方式进行文件的读写操作

2 与IO的主要区别

IO

IONIO
面向流(Stream Oriented)面向缓冲区(Buffer Oriented)
阻塞IO(Blocking IO)非阻塞IO(Non Blocking IO)
选择器(Selectors)

3 通道和缓冲区

NIO系统的核心在于:

  • 通道(Channel)—打开到IO设置(例如:文件, 套接字)连接
  • 缓冲区(Buffer)—一个用于特定基本数据类型的容器
    由java.nio包定义,所有缓冲区都是Buffer抽象类的子类

若需要使用NIO系统

  • 需要获取用于连接IO设备的通道以及用于容纳数据的缓冲区.
  • 然后操作缓冲区,对数据进行处理

简而言之, Channel负责传输,Buffer负责存储

3.1 缓冲区

缓冲区(Buffer):在Java NIO中负责数据的存取. 缓冲区就是数组,用于存储不同数据类型的数据

根据数据类型不同(Boolean除外),提供了相应的缓冲区

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • IntBuffer
  • LongBuffer
  • FloatBuffer
  • DoubleBuffer

上述缓冲区的管理方式几乎一致,通过allocate获取缓冲区

缓冲区存取数据的两个核心方法

  • put()—存入数据到缓冲区中
  • get()—获取缓冲区中的数据

缓冲区中的四个核心属性

  • capacity—容量,标识缓冲区最大存储数据的容量,一旦声明就不能改变
  • limit—界限,表示缓冲区中可以操作数据的大小limit后面的数据不能读写
  • position—位置,表示缓冲区中正在操作数据的位置
    position <= limit <= capacity
  • mark—标记, 表示记录当前position的位置,可以通过reset()恢复到mark位置
    0 <= mark <= position <= capacity

3.2 直接缓冲区与非直接缓冲区

  • 非直接缓冲区—通过allocate()方法分配缓冲区,将缓冲区建立在JVM的内存中
  • 直接缓冲区—通过allocateDirect()方法分配直接缓冲区,将缓冲区建立在物理内存中,可以提高效率

字节缓冲区要么是直接的,要么是非直接的. 如果为直接字节缓冲区,则JVM会尽最大努力直接在此缓冲区上执行本机的I/O操作

也就是说,在每次调用基础操作系统的一个本机I/O操作之前(或之后),虚拟机都会尽量避免将缓冲区中的内容复制到中间缓冲区中(或从中间缓冲区中复制内容)

直接字节缓冲区可以通过调用此类的allocateDirect()方法来创建. 此方法返回的缓冲区进行分配和取消分配所需成本通常高于非直接缓冲区. 直接缓冲区的内容可以在主流在常规的垃圾回收器之外. 因此, 他们对应用程序的内容需求量造成的影响可能并不明显. 所以, 建议将直接缓冲区主要分配给哪些容易受基础系统的本机I/O操作影响的大型, 持久的缓冲区.

一般情况下,最好仅在直接缓冲区能在程序性能方面带来明显好处时分配它们

直接缓冲区还可以通过FileChannel的map()方法将文件区域直接映射到内存中来创建. 该方法返回MappedByteBuffer.

Java平台的实现有助于通过JNI从本机代码创建直接字节缓冲区.

如果以上这些缓冲区中某个缓冲区实例指的是不可用访问的内存区域,则试图访问该区域不会更改该缓冲区的内容.并且将会在访问期间或稍后的某个时间导致抛出不确定的异常

字节缓冲区是直接缓冲区还是非直接缓冲区可以通过其isDirect()方法来确定.提供此方法是为了能够在性能关键代码中执行显示缓冲区管理

如下图所示
非直接缓冲区

直接缓冲区

3.3 通道

通道(Channel)—由java.nio.channels包定义的
Channel表示IO源与目标打开的连接

用于源节点和目标节点的连接, 在Java NIO中负责缓冲区中的数据传输. Channel本身不存储数据,因此需要配合缓冲区进行传输

Channel类似于传统的"流", 只不过Channel本身不能直接访问数据,Channel只能与Buffer进行交互

CPU直接处理I/O请求
CPU直接处理I/O请求
通过DMA—直接存储器处理IO请求
通过DMA---直接存储器处理IO请求
通过通道处理IO请求
通过通道处理IO请求

3.3.1 主要实现类

java.nio.channels.Channel接口

  • FileChannel—文件传输
  • SocketChannel—网络传输(客户端)
  • ServerSocketChannel—网络传输(服务端)
    -DatagramChannel—网络传输, UDP

获取通道

  1. Java针对支持通道的类提供了getChannel()方法
  • 本地IO
    • FileInputStream/FileOutputStream
    • RandomAccessFile
  • 网络IO
    • Socket
    • ServerSocket
    • DatagramSocket
  1. 在JDK 1.7中的NIO针对各个通道提供了静态方法open()
  2. 在JDK 1.7中的Files工具类的newByteChannel()
  3. 通道之间的数据传输
    • transferFrom
    • transferTo
      两者也是通过直接缓冲区传递数据

3.4 分散(Scatter)和聚集(Gather)

  • 分散读取Scatter Reads是指从Channel中读取的数据分散到各个Buffer中

注意: 按照缓冲区的顺序,从Channel中读取的数据依次将Buffer填满

  • 聚集写入Gather Writes是指将多个Buffer中的数据"聚集"到Channel

注意: 按照缓冲区的顺序,写入position和limit之间的数据到Channel

3.5.字符集

Charset

  • 编码—字符串 —> 字节数组
  • 解码—字节数组 —>字符串

4 NIO非阻塞式

4.1 阻塞与非阻塞

传统的的IO流都是阻塞的. 也就是说,当一个线程调用read()或write()时,该线程被阻塞, 直到有一些数据被读取或写入, 该线程在此期间不能执行其他任务.

因此, 在完成网络通信进行IO操作时, 由于线程会阻塞, 所以服务器补习为每个客户端都提供一个独立的线程进行处理, 当服务端需要处理大量客户端时, 性能急剧下降


Java NIO是非阻塞式的. 当线程从某通道进行读写数据时, 若没有数据可用时, 该线程可以进行其他任务, 线程通常将非阻塞IO的空闲时间用于在其他通道上执行IO操作, 所以单独的线程可以管理多个输入和输出通道

因此, NIO可以让服务端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端

4.2 NIO

使用NIO完成网络通信的三个核心

  • 通道(Channel)—负责连接
  • 缓冲区(Buffer)—负责数据的存储
  • 选择器(Selector)—是SelectableChannel的多路复用器
    用于监控SelectableChannel的IO状况

4.3 选择器

选择器(Selector)是SelectableChannel对象的多路复用器

Selector可以同时监控多个SelectableChannel的状态, 也就是说, 利用Selector可以使一个单独的线程管理多个Channel. Selector是非阻塞IO的核心

SelectableChannel的结构如下:

  • SelectableChannel
    • AbstractSelectableChannel
      • SocketChannel
      • ServerSocketChannel
      • DatagramChannel

4.3.1 SelectionKey

  • 当调用register(Selector sel, int pos) 将通道注册选择器时, 选择器对通道的监听事件,需要通过第二个参数ops指定

  • 可以监听的事件类型(可使用SelectionKey的四个常量表示)

    • 读—SelectionKey.OP_READ
    • 写—SelectionKey.OP_WRITE
    • 连接—SelectionKey.OP_CONNECT
    • 接收—SelectionKey.OP_ACCEPT

若注册时不止监听一个事件,则可以使用"位或"操作符连接

内容概要:本文详细介绍了一种基于Simulink的表贴式永磁同步电机(SPMSM)有限控制集模型预测电流控制(FCS-MPCC)仿真系统。通过构建PMSM数学模型、坐标变换、MPC控制器、SVPWM调制等模块,实现了对电机定子电流的高精度跟踪控制,具备快速动态响应和低稳态误差的特点。文中提供了完整的仿真建模步骤、关键参数设置、核心MATLAB函数代码及仿真结果分析,涵盖转速、电流、转矩和三相电流波形,验证了MPC控制策略在动态性能、稳态精度和抗负载扰动方面的优越性,并提出了参数自整定、加权代价函数、模型预测转矩控制和弱磁扩速等优化方向。; 适合人群:自动化、电气工程及其相关专业本科生、研究生,以及从事电机控制算法研究与仿真的工程技术人员;具备一定的电机原理、自动控制理论和Simulink仿真基础者更佳; 使用场景及目标:①用于永磁同步电机模型预测控制的教学演示、课程设计或毕业设计项目;②作为电机先进控制算法(如MPC、MPTC)的仿真验证平台;③支撑科研中对控制性能优化(如动态响应、抗干扰能力)的研究需求; 阅读建议:建议读者结合Simulink环境动手搭建模型,深入理解各模块间的信号流向与控制逻辑,重点掌握预测模型构建、代价函数设计与开关状态选择机制,并可通过修改电机参数或控制策略进行拓展实验,以增强实践与创新能力。
根据原作 https://pan.quark.cn/s/23d6270309e5 的源码改编 湖北省黄石市2021年中考数学试卷所包含的知识点广泛涉及了中学数学的基础领域,涵盖了实数、科学记数法、分式方程、几何体的三视图、立体几何、概率统计以及代数方程等多个方面。 接下来将对每道试题所关联的知识点进行深入剖析:1. 实数与倒数的定义:该题目旨在检验学生对倒数概念的掌握程度,即一个数a的倒数表达为1/a,因此-7的倒数可表示为-1/7。 2. 科学记数法的运用:科学记数法是一种表示极大或极小数字的方法,其形式为a×10^n,其中1≤|a|<10,n为整数。 此题要求学生运用科学记数法表示一个天文单位的距离,将1.4960亿千米转换为1.4960×10^8千米。 3. 分式方程的求解方法:考察学生解决包含分母的方程的能力,题目要求找出满足方程3/(2x-1)=1的x值,需通过消除分母的方式转化为整式方程进行解答。 4. 三视图的辨认:该题目测试学生对于几何体三视图(主视图、左视图、俯视图)的认识,需要识别出具有两个相同视图而另一个不同的几何体。 5. 立体几何与表面积的计算:题目要求学生计算由直角三角形旋转形成的圆锥的表面积,要求学生对圆锥的底面积和侧面积公式有所了解并加以运用。 6. 统计学的基础概念:题目涉及众数、平均数、极差和中位数的定义,要求学生根据提供的数据信息选择恰当的统计量。 7. 方程的整数解求解:考察学生在实际问题中进行数学建模的能力,通过建立方程来计算在特定条件下帐篷的搭建方案数量。 8. 三角学的实际应用:题目通过在直角三角形中运用三角函数来求解特定线段的长度。 利用正弦定理求解AD的长度是解答该问题的关键。 9. 几何变换的应用:题目要求学生运用三角板的旋转来求解特定点的...
Python基于改进粒子群IPSO与LSTM的短期电力负荷预测研究内容概要:本文围绕“Python基于改进粒子群IPSO与LSTM的短期电力负荷预测研究”展开,提出了一种结合改进粒子群优化算法(IPSO)与长短期记忆网络(LSTM)的混合预测模型。通过IPSO算法优化LSTM网络的关键参数(如学习率、隐层节点数等),有效提升了模型在短期电力负荷预测中的精度与收敛速度。文中详细阐述了IPSO算法的改进策略(如引入自适应惯性权重、变异机制等),增强了全局搜索能力与避免早熟收敛,并利用实际电力负荷数据进行实验验证,结果表明该IPSO-LSTM模型相较于传统LSTM、PSO-LSTM等方法在预测准确性(如MAE、RMSE指标)方面表现更优。研究为电力系统调度、能源管理提供了高精度的负荷预测技术支持。; 适合人群:具备一定Python编程基础、熟悉基本机器学习算法的高校研究生、科研人员及电力系统相关领域的技术人员,尤其适合从事负荷预测、智能优化算法应用研究的专业人士。; 使用场景及目标:①应用于短期电力负荷预测,提升电网调度的精确性与稳定性;②为优化算法(如粒子群算法)与深度学习模型(如LSTM)的融合应用提供实践案例;③可用于学术研究、毕业论文复现或电力企业智能化改造的技术参考。; 阅读建议:建议读者结合文中提到的IPSO与LSTM原理进行理论学习,重点关注参数优化机制的设计思路,并动手复现实验部分,通过对比不同模型的预测结果加深理解。同时可拓展尝试将该方法应用于其他时序预测场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值