
内核缓冲区与进程缓冲区应用程序的IO *** 作实际上不是物理设备级别的读写,而是缓存的复制。 (底层的读写交换系统内核完成,在内核缓冲区和进程缓冲区之间进行数据交换。)
系统调用流程 数据交换流程 Linux系统文件句柄数量默认值为1024内核缓冲区:减少底层系统的频繁中断所导致的时间损耗、性能损耗。(只有一个)
进程缓冲区:每个用户程序(进程)都有自己独立的缓冲区。
read:内核到进程
write:进程到内核
IO *** 作就是内核缓冲区和进程缓冲区之间的数据交换
java NIO java NIO(异步非阻塞IO、 New IO)在开机启动文件设置
ulimit -SHn 1000000
-S软性极限值 超出报警
-H硬性极限值 不能超出
要彻底解除Linux系统的最大文件打开数量的限制,可以通过编辑Linux的极限配置文件/etc/security/limits.conf来做到。修改此文件,加入如下内容:soft nofile 1000000 hard nofile 1000000soft nofile表示软性极限,hard nofile表示硬性极限。
NIO和OIO的对比NIO弥补了原来面向流的OIO同步阻塞的不足,为标准Java代码提供了高速、面向缓冲区的IO。
三个核心组件1)OIO是面向流(Stream Oriented)的,NIO是面向缓冲区(Buffer Oriented)的。
2)OIO的 *** 作是阻塞的,而NIO的 *** 作是非阻塞的。
3)OIO没有选择器(Selector)的概念,而NIO有选择器的概念。
NIO Bufferchannel(通道)
一个通道类似于OIO中两个流的结合体,既可以从通道读取数据,也可以向通道写入数据。
buffer(缓冲区)
完成NIO的非阻塞读写 *** 作,缓冲区的使用是面向流进行读写 *** 作的OIO所没有的
selector(选择器)
一个线程可以查询多个通道的IO事件的就绪状态。底层的 *** 作系统IO多路复用技术的支持。
Buffer的成员属性 NIO Buffer重要方法1)Buffer本质上是一个内存块(数组)。写入和读取的交替访问
2)Buffer类是一个抽象类,位于java.nio包中,有8种缓冲区类,分别是ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer、MappedByteBuffer
3)Buffer类是一个非线程安全类。
4)记录读写的状态和位置
Buffer类的基本步骤 NIO Channelallocate(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类的成员属性,不能混淆。
(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事件?
SelectableChannel(可选择通道)这里的IO事件不是对通道的IO *** 作,而是通道处于某个IO *** 作的就绪状态,表示通道具备执行某个IO *** 作的条件。
SelectionKey实现通道可选择性所需要的公共方法。
一个通道若能被选择,则必须继承SelectableChannel类。
选择器使用流程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事件数。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)