【转】NIO的定义和原理是什么?
NIO和IO到底有什么区别?有什么关系?
首先说一下核心区别:
NIO是以块的方式处理数据,但是IO是以最基础的字节流的形式去写入和读出的。所以在效率上的话,肯定是NIO效率比IO效率会高出很多。
NIO不在是和IO一样用OutputStream和InputStream 输入流的形式来进行处理数据的,但是又是基于这种流的形式,而是采用了通道和缓冲区的形式来进行处理数据的。
还有一点就是NIO的通道是可以双向的,但是IO中的流只能是单向的。
还有就是NIO的缓冲区(其实也就是一个字节数组)还可以进行分片,可以建立只读缓冲区、直接缓冲区和间接缓冲区,只读缓冲区很明显就是字面意思,直接缓冲区是为加快 I/O 速度,而以一种特殊的方式分配其内存的缓冲区。
先了解一下什么是通道,什么是缓冲区的概念
通道是个什么意思?
通道是对原 I/O 包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象(通道)。一个 Buffer 实质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。 Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。
正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。
缓冲区是什么意思:
Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中
在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。
缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不 仅仅 是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程
缓冲区的类型:
ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
NIO的底层工作原理
先来了解一下buffer的工作机制:
capacity 缓冲区数组的总长度
position 下一个要操作的数据元素的位置
limit 缓冲区数组中不可操作的下一个元素的位置,limit<=capacity
mark 用于记录当前 position 的前一个位置或者默认是 0
1.这一步其实是当我们刚开始初始化这个buffer数组的时候,开始默认是这样的

2、但是当你往buffer数组中开始写入的时候几个字节的时候就会变成下面的图,position会移动你数据的结束的下一个位置,这个时候你需要把buffer中的数据写到channel管道中,所以此时我们就需要用这个buffer.flip();方法,

3、当你调用完2中的方法时,这个时候就会变成下面的图了,这样的话其实就可以知道你刚刚写到buffer中的数据是在position—->limit之间,然后下一步调用clear();
4、这时底层操作系统就可以从缓冲区中正确读取这 5 个字节数据发送出去了。在下一次写数据之前我们在调一下 clear() 方法。缓冲区的索引状态又回到初始位置。(其实这一步有点像IO中的把转运字节数组 char[] buf = new char[1024]; 不足1024字节的部分给强制刷新出去的意思)

补充:
1、这里还要说明一下
mark,当我们调用 mark() 时,它将记录当前
position 的前一个位置,当我们调用 reset 时,position
将恢复 mark 记录下来的值
2. clear()方法会:清空整个缓冲区。position将被设回0,limit被设置成 capacity的值(这个个人的理解就是当你在flip()方法的基础上已经记住你写入了多少字节数据,直接把position到limit之间的也就是你写入已经记住的数据给“复制”到管道中)
3 . 当你把缓冲区的数局写入到管道中的时候,你需要调用flip()方法将Buffer从写模式切换到读模式,调用flip()方法会将position设回0,并将limit设置成之前position的值。buf.flip();(其实我个人理解的就相当于先记住缓冲区缓冲了多少数据)

NIO其实就是主要利用缓冲区来进行传输字节:
(客户端和服务端又是怎么进行通信和传输的,以后再来更新)
NIO 工作代码示例
public void selector() throws IOException {
//先给缓冲区申请内存空间
ByteBuffer buffer = ByteBuffer.allocate(1024);
//打开Selector为了它可以轮询每个 Channel 的状态
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);//设置为非阻塞方式
ssc.socket().bind(new InetSocketAddress(8080));
ssc.register(selector, SelectionKey.OP_ACCEPT);//注册监听的事件
while (true) {
Set selectedKeys = selector.selectedKeys();//取得所有key集合
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey)
it.next();
if ((key.readyOps() & SelectionKey.OP_ACCEPT) ==
SelectionKey.OP_ACCEPT) {
ServerSocketChannel
ssChannel = (ServerSocketChannel) key.channel();
SocketChannel sc = ssChannel.accept();//接受到服务端的请求
sc.configureBlocking(false);
sc.register(selector,
SelectionKey.OP_READ);
it.remove();
} else if
((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
SocketChannel sc =
(SocketChannel) key.channel();
while (true) {
buffer.clear();
int n =
sc.read(buffer);//读取数据
if (n <= 0) {
break;
}
buffer.flip();
}
it.remove();
}
}
}
}
最后给大家看一下整体的NIO的示意图

【转】NIO的定义和原理是什么?的更多相关文章
- NIO非阻塞网络编程原理
NIO非阻塞网络编程原理 1.NIO基本介绍 Java NIO 全称 java non-blocking IO,是指 JDK 提供的新 API.从 JDK1.4 开始,Java 提供了一系列改进的 输 ...
- 自己定义View Layout过程 - 最易懂的自己定义View原理系列(3)
前言 自己定义View是Android开发人员必须了解的基础 网上有大量关于自己定义View原理的文章.但存在一些问题:内容不全.思路不清晰.无源代码分析.简单问题复杂化等等 今天,我将全面总结自己定 ...
- Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理
Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...
- RPC入门总结(一)RPC定义和原理
转载:深入浅出 RPC - 浅出篇 转载:RPC框架与Dubbo完整使用 转载:深入浅出 RPC - 深入篇 转载:远程调用服务(RPC)和消息队列(Message Queue)对比及其适用/不适用场 ...
- 《转载》RPC入门总结(一)RPC定义和原理
转载:深入浅出 RPC - 浅出篇 转载:RPC框架与Dubbo完整使用 转载:深入浅出 RPC - 深入篇 转载:远程调用服务(RPC)和消息队列(Message Queue)对比及其适用/不适用场 ...
- RPC 定义 和 原理
一.RPC 1. RPC是什么 RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. ...
- SSO的定义、原理、组件及应用
定义: https://baike.baidu.com/item/SSO/3451380 原理: https://blog.csdn.net/cutesource/article/details/58 ...
- JAVA nio 2 定义 Path 类
一旦确认了文件系统上的一个文件或目录,那么就可以定义一个 Path 类来指向它.定义 Path 类可以使用绝对路径.相对路径.路径中带有一个点号“.”(表示当前目录).路径中带有两个点“..”(表示上 ...
- 性能调优必备:NIO的优化实现原理
前言 我们就从底层的网络 I/O 模型优化出发,再到内存拷贝优化和线程模型优化,深入分析下 Tomcat.Netty 等通信框架是如何通过优化 I/O 来提高系统性能的. 网络 I/O 模型优化 网络 ...
随机推荐
- Ruby 全局变量,实例变量,类变量
class Computer $manufacturer = "Mango Computer, Inc." # “$" 是全局变量关键字 @@num_of_instanc ...
- 关于 android 中 postDelayed方法的讲解 (转载)
转自:http://blog.csdn.net/xiabo851205/article/details/7991529 这是一种可以创建多线程消息的函数 使用方法: 1,首先创建一个Handler对象 ...
- python mixin到底是什么 django
1.什么是Mixin 在面向对象编程中,Mixin是一种类,这种类包含了其他类要使用的方法,但不必充当其他类的父类.其他类是如何获取Mixin中的方法因语言的不同而不同.所以有时候Mixin被描述为' ...
- Codeforces - 9D - How many trees? - 简单dp - 组合数学
https://codeforces.com/problemset/problem/9/D 一开始居然还想直接找公式的,想了想还是放弃了.原来这种结构是要动态规划. 状态是知道怎么设了,$t_{nh} ...
- 2016 Multi-University Training Contest 1 GCD【RMQ+二分】
因为那时候没怎么补所以就分到了未搞分组里!!!然后因为标题如此之屌吧= =点击量很高,然后写的是无思路,23333,估计看题人真的是觉得博主就是个撒缺.废话不多说了,补题... update////2 ...
- YCOJ-DFS
DFS搜索是搜索中的一种,即深度优先搜索(Depth First Search),其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次. 图示: 如图,这是邻接矩阵,我 ...
- Git如何克隆Gitlab?Git本地仓库如何上传Gitlab?
首先确保本机已经安装上Git,其次确认可以正常访问Gitlab服务器 环境: Git:Centos 7.x 192.168.126.138 Gitlab: Centos7.x 192.168.126 ...
- mysql文件系统
1 磁盘划分 在一台mysql服务器上,一般是sda做系统,sdb做数据,sdc做日志. 2 磁盘调度策略 linux默认调度策略是cfq,mysql上一般改为deadline echo 'deadl ...
- Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) 题解
真心简单的一场比赛 就是坑比较多(自己太蠢) A是一个水题 3分钟的时候过了 B也是一个比较简单的题 类似的套路见得多了 但是我当时可能比较困 想了一会才想出来 19分钟的时候过掉了 C同样很显然 性 ...
- Magic Numbers CodeForces - 628D
Magic Numbers CodeForces - 628D dp函数中:pos表示当前处理到从前向后的第i位(从1开始编号),remain表示处理到当前位为止共产生了除以m的余数remain. 不 ...