nio java 包_java.nio包学习(一)Buffer

java

NIO Ron Hitchens 著

a4c26d1e5885305701be709a3d33442f.pngnio与io的区别:

1、面向流与面向缓冲区。 nio是面向缓冲区的

Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java

NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

2、阻塞与非阻塞

Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或

write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java

NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。

3、多路复用selector

a4c26d1e5885305701be709a3d33442f.pngBuffer

基本类型数据的缓冲容器,buffer是有限长的某一基本类型数据的线性序列

1、重要属性

capacity buffer的容量,可存储的最大元素数

limit buffer中第一个不可读写元素位置,即buffer中有效元素的个数

position 下一个要读写的元素位置

mark 标记位置

mark

2、基本操作

get和pu相对操作和绝对操作

相对操作,函数没有参数传入,在position基础上进行相对操作,依赖于position

绝对操作,函数传入参数,直接根据参数操作,不会改变position

mark和reset、position

mark用于标记缓冲区的某一位置,

reset将position重设为mark标记的位置

clear、flip、rewind

clear源码:

public final Buffer clear() {

position = 0;

limit = capacity;

mark = -1;

return this;

}

flip源码:buffer写入与读取数据时position都是增长的,为保证读取数据时的顺序,

将有效数据设为position值,position置0。

public final Buffer flip() {

limit = position;

position = 0;

mark = -1;

return this;

}

rewind源码:

public final Buffer

rewind() {

position = 0;

mark = -1;

return this;

}

级联调用

mark、reset等函数的返回值是Buffer对象,故可以使用级联式调用

3、线程安全性

Buffer子类都是非线程安全的,在多线程环境下应考虑同步问题

a4c26d1e5885305701be709a3d33442f.png

注意:该图中的Buffer及其直接子类都是抽象类ByteBuffer

Operating systems perform I/O operations on memory areas. These memory areas, as far as the operating system is concerned, are contiguous sequences of bytes. It's no surprise then that only byte buffers are eligible to participate in I/O operations.(只有字节缓冲区才能参与到I/O操作中,可以看到在channel操作中只会涉及到字节缓冲BytrBuffer) Also recall that the operating system will directly access the address space of the process, in this case the JVM process, to transfer the data. This means that memory areas that are targets of I/O perations must be contiguous sequences of bytes. In the JVM, an array of bytes may not be stored contiguously in memory, or the Garbage Collector could move it at any time. Arrays are objects in Java, and the way data is stored inside that object could vary from one JVM implementation to another.

视图缓冲区

ByteBuffer转成其他Buffer

asCharBuffer

asIntBuffer

asShortBuffer

asLongBuffer

asFloatBuffer

asDoubleBuffer

数据元素视图

getChar()

getInt()

getShort()

getLong()

getFloat()

getDouble()

直接缓冲与间接缓冲

ByteBuffe两种实现,一种是使用JVM堆内存建立缓冲区,一种是直接缓冲区。

如果您向一个通道中传递一个非直接ByteBuffer对象用于写入,通道可能会在每次调用中隐含地进行下面的操作:

I/O操作中的数据都会在I/O设备与应用程序空间之间经历一个“内核缓冲区”。

程序对I/O写数据:使用堆缓冲区会先将数据从堆缓冲区复制到“内核缓冲区”,OS再将数据发送到设备

1.创建一个临时的直接ByteBuffer对象。

2.将非直接缓冲区的内容复制到临时缓冲中。

3.使用临时缓冲区执行低层次I/O操作。

4.临时缓冲区对象离开作用域,并最终成为被回收的无用数据。

Direct Buffer创建和销毁的代价很高,所以要用在尽可能重用的地方。

Direct Buffer使用场景:

大量原生类型数据使用

频繁IO操作

系统处理响应速度要求快且稳定

典型场景是网络数据传输, 可考虑合理应用DirectBuffer.

创建:

allocate()函数与allocateDirect()函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值