NIO学习收藏

学习NIO

NIO和BIO最大的区别就是IO是面向流的,NIO面向缓冲区的。而且NIO一个很大的改进是可以通过native函数直接在系统内存区分配内存,避免了在用户进程和系统进程间来回的复制数据引起的效率问题。BIO是同步阻塞的,NIO的同步非阻塞的。
要理解NIO需要理解阻塞、非阻塞、同步和非同步的概念。

1.阻塞和非阻塞

阻塞和非阻塞是进程在访问数据的时候,数据是否准备就绪时的一种处理方式。

  1. 阻塞:当数据没有准备好的时候,往往需要等待数据准备好过后才能处理其他事情,否则一直等待在那里,BIO中的read()write()accept()就是阻塞的。
  1. 非阻塞:数据没有准备好,直接返回,不需要等待。

2.同步和非同步

我理解的同步和异步是基于应用程序和操作系统处理IO时间所采用的方式不同。

同步:应用程序直接参与IO读写的操作
异步:所有的IO读写交给操作系统去处理,应用程序并不需要去完成真正的IO操作,当操作系统完成IO操作后,给应用程序一个通知就行了。

3.BIO和NIO的IO模型

BIO是同步阻塞式IO模型,要实现多个IO操作的快速响应,一般让读写方法加入到线程里面,但是这样对线程的性能开销比较大。

NIO是多路复用IO模型,参考linux的select的灵感实现同步非阻塞IO,IO事件交给一个单独的线程来处理,去用这个线程轮询IO事件,事件发生时,通知相应的读写线程,这样的话,阻塞不是所有的IO线程,只需要阻塞一个线程就行了.

一个易于理解但有点牵强的例子: 餐厅吃饭,每个客人点完菜不是立刻就能吃上的,需要厨师烹制和排队等待时间,假如顾客只能呆在厨房边干等着自己菜,不能干其他事情,这样当然是不现实的,特别是顾客越多,厨房越拥挤(对应于BIO)
所以现实中,都会有服务员这一角色,顾客只要坐在桌上等着就行了,可以玩手机、聊天,服务员会不断的到厨房看着哪桌的菜煮了直接就端上去(对应于NIO)

4.java NIO的API

java NIO有3个核心组件BufferChannelSelector ,这里先只介绍一下Buffer

Buffer是存储基本类型数据的容器。学习Buffer,需要理解Buffer的4个关键属性

  • capacity (总容量)
  • position (指针当前位置)
  • limit (读/写边界位置)
  • mark (标记位置)
    Buffer是一个接口,基本的8种数据除了boolean都对应一种Buffer,如ByteBuffer,CharBuffer
    初始化一个CharBuffer,调用allocate(capacity)
 CharBuffer buffer = CharBuffer.allocate(8);

    
    
  • 1

初始化后,4个属性的含义如下
img1
当调用put(),get()时,position指针位置就会向前移动

buffer.put("Hello");
System.out.println(buffer.position());

    
    
  • 1
  • 2

img
mark()方法,mark指针移动到当前位置

buffer.mark();
buffer.put("g");

    
    
  • 1
  • 2

img
limit()会把limit指针移动到当前位置或者指定位置,给limit,capacity之间的位置放置数据会抛出BufferUnderflowException异常

buffer.put("g");
buffer.limit();
buffer.put("a");

    
    
  • 1
  • 2
  • 3

img
clear() 把position设为0,limit设为capacity,并且清除mark标记。(写入新数据)

buffer.reset();

    
    
  • 1

img
flip() 把limit设为当前position,把position设为0,同时清除mark标记(转写为读)

buffer.put("Hellog");
buffer.flip();

    
    
  • 1
  • 2

img
rewind()position设为0,limit不变,同时清除mark标记。(数据重写)

buffer.put("Hellog");
buffer.rewind();

    
    
  • 1
  • 2

img
compact()将 position 与 limit之间的数据复制到buffer的开始位置,且 position = limit -position,limit = capacity,同时清除mark标记,但如果position 与limit 之间没有数据的话,就不会进行复制(常用于防止写出到Channel不完整)

buffer.put("Hellog");
buffer.limit();
buffer.compact();

    
    
  • 1
  • 2
  • 3

img
reset() 将position恢复到mark的位置上。即position=mark,且不清除mark标记

buffer.put("Hello");
buffer.mark();
buffer.put("gay");
buffer.reset();

    
    
  • 1
  • 2
  • 3
  • 4

img

Channel、Selector 见(二)

                                </div><div><div></div></div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-60ecaf1f42.css" rel="stylesheet">
                            </div>
</article>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值