NIO 概述

前面说到 BIO 有着创建线程多,阻塞 CPU 等问题,因此为解决 BIO 的问题,NIO 作为同步非阻塞 IO模型,随 JDK1.4 而出生了。

在前面我们反复说过4个概念:同步、异步、阻塞、非阻塞。因此,我们就首先用最简单的语言说一下他们的区别,这里,我们心里暂时有个概念即可,在后面的学习过程中,还会对其进行深入的探讨学习。

概念对比

首先,我们先要确立一个概念,就是一个IO操作其实是分为两步的,

  1. 发起IO请求,即准备数据和区域;
  2. 实际的IO操作。

而区分一个 IO模型是同步还是异步,就取决于在进行第2个步骤时,即实际进行读写过程中,其是否会阻塞线程,如果会阻塞,那么就是同步的,如果不会(这里就需要操作系统内核来进行操作了),而是完成后,再通知操作线程,那么其就是异步的(AIO 就是 OS 来完成文件读写操作,在完成后通过消息机制来通过线程读写完毕)。

紧接着,区分一个模型是阻塞还是非阻塞,而是看其在数据没有准备完毕时,即连接建立后,但还没有数据过来,请求是需要卡在这等待,还是可以去干其他的事。

作为上文所述的 BIO 来说,首先因为数据是否读写完成,需要其一直在循环里判断,因此其是同步的,并且如果没有数据的话,其会一直卡在 read 操作上,不能继续往下执行,因此 BIO 是一种同步阻塞模型。

而 NIO 的数据读写完成与否,也需要自己来判断,因此也是同步的,但其只有当发生真正读写时,才会进行操作,如果没有准备完毕的话,则可以去做其他的事,因此 NIO 是一个同步非阻塞 IO模型。

总结一下,我们看一个模型是同步还是异步,其实看的是数据准备完毕后的消息通知机制;看是阻塞还是非阻塞的,则是看线程在请求后的线程状态。

下面就让我们来看一下 NIO 的基本概念。

NIO基本介绍

  1. 从 JDK1.4 后,官方引入的 IO 新特性,称为 NIO,是一个同步非阻塞模型;
  2. 相关类在 java.nio 包下,有 3大核心组件,Channel,Buffer,Selector
  3. NIO 是面向缓存区编程的,或者说可以是面向块的,而不是面向字节,因此极大提高了编程的灵活性;
  4. NIO 因为其核心组件和面向缓存区编程的特性,因此 数据总是从 Channel 读取到 Buffer 中,或者从Buffer 读取到 Channel 中,而 Selector 的作用就是监听多个 Channel,当 Channel 中有请求需要处理,就进行处理
  5. 。。。。。(官网或者搜一下,有很多,在这里就不多赘述了)

组件介绍

Buffer

缓存区本质是一个可以读写程序的内存块,我们可以将其简单理解为一个容器。在其内部还提供了一些方法,方便编程人员对其进行操作。

其所有可用子类如 ByteBuffer 等继承的父类为 Buffer,其有一些公有属性需要牢记。

属性 说明
mark 标记位,在调用 mark() 方法后,可以将当前 position 设为标记,后续在调用 reset() 方法时,就可以将 position 重置回该位置,如果不设置,则为负数,那么在调用 reset 时,会报错。(一般不需要设置)
position 缓存区内将要被写或读的节点下标,该值不能为负数,且永远小于等于 limit
limit 缓存区内第一个不能写或读的节点下标,该值不能为负数,且永远小于等于 capacity
capacity 缓存区被创建时指定的大小,该值不能为负数,且无法更改
mark <= position <= limit <= capacity

Buffer 代码演示

 IntBuffer intBuffer = IntBuffer.allocate(5);
for (int i = 1; i <= intBuffer.capacity(); i++) {
intBuffer.put(i);
}
// 翻转,读写切换
intBuffer.flip();
while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
} intBuffer.position(0);
for (int i = 1; i <= intBuffer.capacity(); i++) {
intBuffer.put(i * i);
}
intBuffer.flip();
while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
}
}

从上述代码中,可以看到 缓存区是一个可读可写的区域,且像数组容器一样可以在里面通过下标的方式进行移动,从而修改指定地方内容。

Channel

Channel 是流中的一个组件,在使用过程中,通过流来生成。

Channel 是 NIO 中的一个接口,其实现类中,我们使用的比较多的有FileChannel,ServerSocketChannel,SocketChannelDatagramChannel,其中 FileChannel 用于文件的读写,ServerSocketChannel 和 SocketChannel 用于TCP数据读写,DatagramChannel 用于 UDP 数据读写。

这里只描述一些 Channel 的一些简单概念,在后续文章:《文件操作》中,再用代码详细展示 Channel 的作用。

Selector

selector 解决的是 BIO 的线程阻塞和一个请求就需要创建一个线程的问题。selector 可以监控多个 Channel,如果对应的 Channel 有 Event 发生,就可以获取对应 Event,然后根据获取 Event 的不同去进行不同的处理逻辑,这样就不必每个请求都创建线程,并且只有当真正有读写事件发生时,才会进行操作。

也是只描述 Selector 的一些简单概念,在后续文章:《网络编程》中,再用代码详细展示 Selector 的作用。

总结

在本文中,我们初步介绍了 NIO 的概念,以及其的 3个核心组件:Buffer,Channel 和 Selector。

在后续的文章中,我们将对其分别进行介绍,通过 NIO 来逐步引入 Netty 的实现。

本文中代码已上传到 GitHub 上,地址为 https://github.com/wb1069003157/nettyPre-research ,欢迎大家来讨论,探讨。

文章在公众号「iceWang」第一手更新,有兴趣的朋友可以关注公众号,第一时间看到笔者分享的各项知识点,谢谢!笔芯!

Netty学习(2):IO模型之NIO初探的更多相关文章

  1. Netty学习之IO模型

    目录 1.1 同步.异步.阻塞.非阻塞     同步 VS 异步         同步         异步     阻塞 VS 非阻塞         阻塞         非阻塞     举例   ...

  2. Netty学习(4):NIO网络编程

    概述 在 Netty学习(3)中,我们已经学习了 Buffer 和 Channel 的概念, 接下来就让我们通过实现一个 NIO 的多人聊天服务器来深入理解 NIO 的第 3个组件:Selector. ...

  3. IO模型之NIO代码及其实践详解

    一.简介 NIO我们一般认为是New I/O(也是官方的叫法),因为它是相对于老的I/O类库新增的( JDK 1.4中的java.nio.*包中引入新的Java I/O库).但现在都称之为Non-bl ...

  4. 5月2日 python学习总结 IO模型

    IO模型 1.阻塞IO 2.非阻塞IO 3.多路复用IO 4.异步IO 一.阻塞IO blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了. 实际上,除非 ...

  5. Netty学习笔记(1)NIO三大组件

    1. Channel channel 有一点类似于 stream,它就是读写数据的双向通道,可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入 channel,而之前 ...

  6. 聊聊Netty那些事儿之从内核角度看IO模型

    从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架. 它的设计异常优雅简洁,扩展性高,稳定性强.拥有非常详细完整的用户文档. 同时内置了很多非常有用的模块 ...

  7. Netty 学习(一):服务端启动 & 客户端启动

    Netty 学习(一):服务端启动 & 客户端启动 作者: Grey 原文地址: 博客园:Netty 学习(一):服务端启动 & 客户端启动 CSDN:Netty 学习(一):服务端启 ...

  8. Netty 学习(二):服务端与客户端通信

    Netty 学习(二):服务端与客户端通信 作者: Grey 原文地址: 博客园:Netty 学习(二):服务端与客户端通信 CSDN:Netty 学习(二):服务端与客户端通信 说明 Netty 中 ...

  9. IO模型及高性能网络架构分析

    前言 操作系统一次IO调用过程 应用程序发起的一次IO操作包含两个阶段: IO调用:应用程序进程向操作系统内核发起调用. IO执行:操作系统内核完成IO操作. 操作系统内核完成IO操作还包括两个过程: ...

随机推荐

  1. 基于Arduino的红外遥控

    1.红外接收头介绍  一.什么是红外接收头?  红外遥控器发出的信号是一连串的二进制脉冲码.为了使其在无线传输过程中免受其他红外信号的干扰,通常都是先将其调制在特定的载波频率上,然后再经红外发射二极管 ...

  2. Arrays.sort() VS Arrays.parallelSort()

    英文原文地址:Arrays.sort vs Arrays.parallelSort 作者:baeldung 翻译:高行行 1. 概述 我们都使用过 Arrays.sort() 对对象或原始数据类型数组 ...

  3. how to render html tag

    使用autoescaping If autoescaping is turned on in the environment, all output will automatically be esc ...

  4. 你的应用安全吗? ——用Xray和Synk保驾护航

    一.背景 在当下软件应用的开发过程当中,自研的内部代码所占的比例逐步地减少,开源的框架和共用库已经得到了广泛的引用.如下图所示,在一个Kubernetes部署的应用当中,我们自己开发代码所占的比例可能 ...

  5. [Micropython]TPYBoard v202 智能WIFI远控小车

    转载请注明文章来源,更多教程可自助参考docs.tpyboard.com,QQ技术交流群:157816561,公众号:MicroPython玩家汇 前言---------------------- 之 ...

  6. 12.Android-SQLiteOpenHelper使用

    1.SQLite介绍 SQLite,是一款轻型的数据库,它的优缺点有如下: 轻量级,适合嵌入式设备,并且本身不依赖第三方的软件,使用它也不需要“安装”. 并发(包括多进程和多线程)读写方面的性能不太理 ...

  7. 最短路Dijkstra算法模板

    // // dijkstra妯℃澘.cpp // algorithm // // Created by david.xu on 2018/8/6. // Copyright 漏 2018骞?david ...

  8. 网络流入门题目 - bzoj 1001

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点 ...

  9. DP-直线分割递推

    在 DP  里有一类是直线分割平面的问题 , 也是属于递推 类的 . 一 . 直线分割平面的问题 先考虑第一个小问题 : n 条直线最多可以将平面分割成几部分 ? 想想 最优的分割方法是怎样的呢 ? ...

  10. [题解]CSP2019 Solution - Part A

    至于为什么是 \(\text{Part A}\) 而不是 \(\text{Day 1}\) 那是因为 Day1 T3 还没改 (那这六题的 \(\text{solution}\) 就按难度顺序写吧) ...