栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

20220422java学习笔记-------------NIO

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

20220422java学习笔记-------------NIO

高并发IO的底层原理 IO读写的基本原理

应用程序的IO操作实际上不是物理设备级别的读写,而是缓存的复制。 (底层的读写交换系统内核完成,在内核缓冲区和进程缓冲区之间进行数据交换。)

内核缓冲区与进程缓冲区

内核缓冲区:减少底层系统的频繁中断所导致的时间损耗、性能损耗。(只有一个)

进程缓冲区:每个用户程序(进程)都有自己独立的缓冲区。

read:内核到进程

write:进程到内核

IO操作就是内核缓冲区和进程缓冲区之间的数据交换

系统调用流程

数据交换流程 

Linux系统文件句柄数量默认值为1024 

在开机启动文件设置

ulimit -SHn 1000000

-S软性极限值  超出报警

-H硬性极限值  不能超出

要彻底解除Linux系统的最大文件打开数量的限制,可以通过编辑Linux的极限配置文件/etc/security/limits.conf来做到。修改此文件,加入如下内容:soft nofile 1000000 hard nofile 1000000soft nofile表示软性极限,hard nofile表示硬性极限。

java NIO java NIO(异步非阻塞IO、 New IO)

NIO弥补了原来面向流的OIO同步阻塞的不足,为标准Java代码提供了高速、面向缓冲区的IO。

NIO和OIO的对比

1)OIO是面向流(Stream Oriented)的,NIO是面向缓冲区(Buffer Oriented)的。

2)OIO的操作是阻塞的,而NIO的操作是非阻塞的。

3)OIO没有选择器(Selector)的概念,而NIO有选择器的概念。

三个核心组件

channel(通道)

一个通道类似于OIO中两个流的结合体,既可以从通道读取数据,也可以向通道写入数据。

buffer(缓冲区)

完成NIO的非阻塞读写操作,缓冲区的使用是面向流进行读写操作的OIO所没有的

selector(选择器)

一个线程可以查询多个通道的IO事件的就绪状态。底层的操作系统IO多路复用技术的支持。

NIO Buffer 

1)Buffer本质上是一个内存块(数组)。写入和读取的交替访问

2)Buffer类是一个抽象类,位于java.nio包中,有8种缓冲区类,分别是ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer、MappedByteBuffer

3)Buffer类是一个非线程安全类。

4)记录读写的状态和位置

 Buffer的成员属性

NIO Buffer重要方法 

 allocate(x)

实例Buffer对象 空间大小为x*4个字节

put()

写入元素到缓冲区

flip()

将写模式转换成读模式

clean()

清空缓冲区,可以将模式重置为读模式

(1)将position清零。

(2)limit设置为capacity最大容量值,可以一直写入,直到缓冲区写满。

compact()

压缩,可以将模式重置为读模式

get()

读取缓冲区数据

rewind()

重新读取

mark()

记住当前位置(position)的值保存到mark(标签)中

rest()

把Mark的值恢到position中

注意:Buffer.mark()和Buffer.reset()两个方法都涉及mark属性的使用。mark()方法与mark属性的名字虽然相同,但是一个是Buffer类的成员方法,一个是Buffer类的成员属性,不能混淆。

Buffer类的基本步骤

NIO Channel

(1)FileChannel:文件通道,用于文件的数据读写。更高效文件复制通道的transferFrom()方法

(2)SocketChannel:套接字通道,用于套接字TCP连接的数据读写,可以在服务端和客户端

(3)ServerSocketChannel:服务器套接字通道(或服务器监听通道),允许我们监听TCP连接请求,为每个监听到的请求创建一个SocketChannel通道,只能在服务端

(4)DatagramChannel:数据报通道,用于UDP的数据读写。

无论是ServerSocketChannel还是SocketChannel,都支持阻塞和非阻塞两种模式。如何进行模式的设置呢?调用configureBlocking()方法

(1)socketChannel.configureBlocking(false)设置为非阻塞模式。

(2)socketChannel.configureBlocking(true)设置为阻塞模式。

在阻塞模式下,SocketChannel的连接、读、写操作都是同步阻塞式的,在效率上与Java OIO面向流的阻塞式读写操作相同。

在非阻塞模式下,通道的操作是异步、高效的,这也是相对于传统OIO的优势所在。

 

NIO Selector (选择器) 选择器与注册

完成IO的多路复用,其主要工作是通道的注册、监听、事件查询。选择器和通道的关系是监听和被监听的关系。

一个单线程处理一个选择器,一个选择器可以监控很多通道。

通道和选择器之间的关联通过register(注册)的方式完成。调用通道的Channel.register(Selector sel,int ops)方法,可以将通道实例注册到一个选择器中。register方法有两个参数:第一个参数指定通道注册到的选择器实例;第二个参数指定选择器要监控的IO事件类型。可供选择器监控的通道IO事件类型包括以下四种:

(1)可读:SelectionKey.OP_READ。

(2)可写:SelectionKey.OP_WRITE。

(3)连接:SelectionKey.OP_CONNECT。

(4)接收:SelectionKey.OP_ACCEPT。

 什么是IO事件?

这里的IO事件不是对通道的IO操作,而是通道处于某个IO操作的就绪状态,表示通道具备执行某个IO操作的条件。

SelectableChannel(可选择通道)

实现通道可选择性所需要的公共方法。

一个通道若能被选择,则必须继承SelectableChannel类。

 SelectionKey

SelectionKey就是那些被选择器选中的IO事件。选择器中注册过,就会被选择器选中,并放入SelectionKey中可以获得通道的IO事件类型(比如SelectionKey.OP_READ),还可以获得发生IO事件所在的通道。

选择器使用流程 

注: 处理完成后,需要将选择键从SelectionKey集合中移除,以防止下一次循环时被重复处理。SelectionKey集合不能添加元素,如果试图向SelectionKey中添加元素,则将抛出java.lang.UnsupportedOperationException异常。

select()方法

用于选择就绪的IO事件的select()方法有多个重载的实现版本,具体如下:

(1)select():阻塞调用,直到至少有一个通道发生了注册的IO事件。

(2)select(long timeout):和select()一样,但最长阻塞时间为timeout指定的毫秒数。

(3)selectNow():非阻塞,不管有没有IO事件都会立刻返回。

select()方法的返回值是整数类型(int),表示发生了IO事件的数量,即从上一次select到这一次select之间有多少通道发生了IO事件,更加准确地说是发生了选择器感兴趣(注册过)的IO事件数。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/850409.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号