NIO

什么是NIO?

NIO 全程 java non-blocking IO,是指jdk1.4 提供的新api(NEW IO)

NIO与IO的区别

NIO 特点:非阻塞,面向缓冲区
IO 特点:阻塞式,面向流

阻塞与非阻塞

java io 是阻塞式的,当一个线程调用read 或者write方法后开始阻塞,直到读取到数据或者写入数据完成,该线程一直处于阻塞状态不能做其他事情。
java nio 通过选择器实现非阻塞式IO,通过一个专门的选择器线程来监视 读请求或者写请求是否已经具备完整条件。
非阻塞读:如某个线程发送一个读请求,则它只能获取到当前可用的数据,如果没有可用的数据直接返回,而不是阻塞在这里,直到数据变得可读取。在数据变得可读取之前该线程是可以继续处理其他任务的。
非阻塞写:如某个线程发送写请求,需要写一些数据到通道中,但不需要等到将所有数据都完全写入,该线程可以同时做其他任务。
线程通常将非阻塞的IO的空闲时间用来执行其他通道的IO任务,所以一个单独的线程可以管理多个输入和输出通道。

NIO重要属性

Channel

通道:channel 是在rt.jar java.util.nio 包下定义的,表示io源与目标打开的链接。
通道不能直接传输数据只能配合缓冲区使用。
通道类似于流 ,但是通道是双向的,即可以将通道指向的目标源数据读入到缓冲区,也可以将缓冲区数据写入到链接通道的目标源。通道好比是铁路,缓冲区为火车,火车载人,通过铁路来运输。
主要方法
将通道指向的目标源读到dst缓冲区中
将数据写入目标源:
java.nio.channels.SeekableByteChannel#read(ByteBuffer dst)

向通道指向的目标源写入数据
java.nio.channels.SeekableByteChannel#write(ByteBuffer dst)

Buffer

缓冲区是存储数据的数组
重要属性
1 capacity:缓冲区容量大小,一旦创建不可改变
2 limit:缓冲区可用数据大小,也就是缓冲区最后一个可操作数据的下标,该下标之后的缓冲区数据不可操作。小于等于capacity
3 position:当前操作的位置。小于等于limit
4 mark:上一次标记的索引位置
重要方法

  • 1.向缓冲区写入数组

put(byte[] src, int offset, int length)
src:要写入的数据
offset:写入数据src的开始下标(从src的offset位置开始)
length:写入数据的长度

将src数组中下标位置从offset开始到长度为length的数据防在缓冲区中。

注意: offset指从数组的offset下标开始获取数据

  • 2.将缓冲区数据读到数组中

get(byte[] dst, int offset, int length)
src:dst数组开始下标
length:读取数据的长度

将缓冲区中的数据读取到byte数组中,数组从索引为 offset位置开始存入length长度的数据

注意: offset指数组的offset下标开始

  • 3.切换读模式
    filp()
    缓冲区从写模式切换到读模式。此时position = 0,limit = 写入数据的最大长度(最后一次写操作的position),mark=-1 标记位清空

  • 4.重读
    rewind()
    缓冲区的数据需要再次读取
    position=0,limit不变,mark=-1

  • 5.清除缓冲区
    clear()
    清除缓冲区,此时将所有属性恢复,position=0,limit=capacity,但是缓冲区数据没有删除。这些数据成为被遗忘的数据。(可以通过设置position于limit来)

  • 6.标记
    mark()
    标记当前位置 mark = position

  • 7.重置
    reset()
    position=mark

Selector

选择器 ,它是Java NIO核心组件中的一个,用于检查一个或多个NIO Channel(通道)的状态是否处于可读、可写。
使用Selector的好处在于: 使用更少的线程来就可以来处理通道了, 相比使用多个线程,避免了线程上下文切换带来的开销。
示例代码:
Selector selector = Selector.open(); channel.configureBlocking(false); SelectionKey key = channel.register(selector, Selectionkey.OP_READ);
channel.configureBlocking(false);
将通道设置为非阻塞式,FileChannel 是阻塞式的不能使用选择器,SocketChannel 网络套接字的通道可以设置为非阻塞式。

register方法的第二个参数是监听事件的类型。选择器可以监听以下四种类型的事件
Connect :链接就 SelectionKey.OP_CONNECT
Accept:接收就绪 SelectionKey.OP_ACCEPT
Read:读就绪 SelectionKey.OP_READ
Write:写就绪 SelectionKey.OP_WRITE

如果需要注册多个事件
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

可以通过以下方法来确定以上事件是否准备就绪,它们都会返回一个布尔类型:
链接就绪:selectionKey.isConnectable();
接收就绪:selectionKey.isAcceptable();
读就绪:selectionKey.isReadable();
写就绪:selectionKey.isWritable();

Set selectedKeys =selector.selectedKeys();

Iterator keyIterator = selectedKeys.iterator();

while(keyIterator.hasNext()) {
    SelectionKey key = keyIterator.next();
    if(key.isAcceptable()) {
        // a connection was accepted by a ServerSocketChannel.
    } else if (key.isConnectable()) {
        // a connection was established with a remote server.
    } else if (key.isReadable()) {
        // a channel is ready for reading
    } else if (key.isWritable()) {
        // a channel is ready for writing
    }
    keyIterator.remove();
}

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

非直接缓冲区

客户端向服务端发送数据,先将数据发送到虚拟机中用户地址中空间的缓存中,然后用户地址空间将数据复制到系统内核地址空间的缓存中,内核地址空间将数据写入到系统的物理磁盘中。

image.png

直接缓冲区

直接缓冲区省去了用户地址空间缓存到内核地址空间缓存的复制过程,用物理内存映射文件来代替,直接将数据存入到物理内存中,然后在将数据存入到物理磁盘中。
可以通过Buffer.allocateDirect 方法来创建直接缓冲区。


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容

  • 转自 http://www.ibm.com/developerworks/cn/education/java/j-...
    抓兔子的猫阅读 2,299评论 0 22
  • # Java NIO # Java NIO属于非阻塞IO,这是与传统IO最本质的区别。传统IO包括socket和文...
    Teddy_b阅读 586评论 0 0
  • Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java I...
    JackChen1024阅读 7,550评论 1 143
  • JAVA NIO基础 ...
    文思li阅读 613评论 0 3
  • NIO概述 Java NIO全称为Non-blocking IO或者New IO,从名字我们知道NIO是非阻塞的I...
    zhong0316阅读 597评论 0 7