Java网络IO BIO NIO AIO

程老师博客原文:http://flychao88.iteye.com/blog/1958431

NIO和IO的区别

Java NIO编程 提供了对块IO的支持,使用块IO的好处是效率更高 
1.   基本 概念 
IO 是主存和外部设备 ( 硬盘、终端和网络等 ) 拷贝数据的过程。 IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成。 
所有语言运行时系统提供执行 I/O 较高级别的工具。 (c 的 printf scanf,java 的面向对象封装 ) 
2.    Java 标准 io 回顾 
Java 标准 IO 类库是 io 面向对象的一种抽象。基于本地方法的底层实现,我们无须关注底层实现。 InputStream\OutputStream( 字节流 ) :一次传送一个字节。 Reader\Writer( 字符流 ) :一次一个字符。 
3.    nio 简介 
nio 是 java New IO 的简称,在 jdk1.4 里提供的新 api 。 Sun 官方标榜的特性如下: 
–     为所有的原始类型提供 (Buffer) 缓存支持。 
–     字符集编码解码解决方案。 
–     Channel :一个新的原始 I/O 抽象。 
–     支持锁和内存映射文件的文件访问接口。 
–     提供多路 (non-bloking) 非阻塞式的高伸缩性网络 I/O 。 
本文将围绕这几个特性进行学习和介绍。 
4.   Buffer&Chanel 
Channel 和 buffer 是 NIO 是两个最基本的数据类型抽象。 
Buffer: 
–        是一块连续的内存块。 
–        是 NIO 数据读或写的中转地。 
Channel: 
–        数据的源头或者数据的目的地 
–        用于向 buffer 提供数据或者读取 buffer 数据 ,buffer 对象的唯一接口。 
–         异步 I/O 支持 
*************************************原文结束,学习笔记开始**********************************************

NIO里面有三个比较核心的部分: Buffer,Channel,Selector
IO                NIO
面向流            面向缓冲
阻塞IO            非阻塞IO
无                选择器
对应解释如下:
1.标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
2.  Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
3.  Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
这块是重点,目前理解的还不深刻。待补充。
****************************************************************************
再次补充:2018.04
一 背景:
先说系统之间的网络通信方式,必要的要素:
1信息格式(为了是参与者都能理解的格式):常见的xml.json,protocol buffer(pb) 等。

2 网络协议:系统间的信息传递依赖于网络。这块侧重于OSI模型参考的7层或者5层协议。

3 通信方式(框架):这才是我们常见的网络I/O模型。

那去银行排队举例子(或者去餐馆吃饭)

阻塞I/O和非阻塞I/O :程序级别,主要描述程序请求操作系统I/o操作后,等待消息通知时,程序如何处理。

    阻塞I/O等待,非阻塞I/O继续执行(使用线程一直轮询,直到网络I/O准备好了)

  举例:1阻塞:排队过程啥也不干。

             2.非阻塞:一边排队,一边玩手机。有线程切换的过程。

同步I/O 和异步I/O: 操作系统级别(与消息的通知机制有关),主要描述的是操作系统在收到程序请求操作网路I/O之后,如何响应: 同步I/O 不响应,直到网络I/O资源准备好。异步I/O返回一个标记,当网络I/O资源准备好之后,再用事件机制返回给程序。

  举例:1同步:排队等通知。

            2.异步:择取一个小纸条上面有我的号码,柜台叫号。

二 阻塞模式

 2.1 同步阻塞

网络编程的基本模型是C/S模型,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程相应,如果没有则会一直等待或者遭到拒绝请求,如果有的话,客户端会线程会等待请求结束后才继续执行。

Java网络IO BIO NIO AIO_第1张图片

  该模型最大的问题就是缺乏弹性伸缩能力,当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,多线程不能从本质上解决:操作系统通知accept是单个线程运行的,线程是系统宝贵资源(创建及切换)。相关代码就是socket编程。

举例:餐厅一个服务员,一份菜单,一个人点完了下一个点。效率最低。

2.2 改进 使用线程池

Java网络IO BIO NIO AIO_第2张图片

实现1个或多个线程处理N个客户端的模型(但是底层还是使用的同步阻塞I/O),通常被称为“伪异步I/O模型“,不是我们俗称的NIO。

2.3 同步非租塞

比如设置了超时时间,再去轮询。

举例:N个服务员,N份菜单,每来一个顾客就有服务员提供菜单点菜,资源消耗大。

三 NIO

 NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。底层依赖操作系统的select,poll,epool,kqueue技术。

Java网络IO BIO NIO AIO_第3张图片

Java对于NIO支持的模型如下,涉及的概念buffer,channel,selector。

3.1 缓冲区 Buffer

    Buffer是一个对象,包含一些要写入或者读出的数据。 在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,也是写入到缓冲区中。任何时候访问NIO中的数据,都是通过缓冲区进行操作。

    缓冲区实际上是一个数组,并提供了对数据结构化访问以及维护读写位置等信息。具体的缓存区有这些:ByteBuffe、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。他们实现了相同的接口:Buffer。

3.2、通道 Channel

    我们对数据的读取和写入要通过Channel,它就像水管一样,是一个通道。通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。 底层的操作系统的通道一般都是全双工的,所以全双工的Channel比流能更好的映射底层操作系统的API。Channel主要分两大类:    SelectableChannel:用户网络读写    FileChannel:用于文件操作

    3.3、多路复用器 Selector

    Selector是Java  NIO 编程的基础。Selector提供选择已经就绪的任务的能力:Selector会不断轮询注册在其上的Channel,如果某个Channel上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通过SelectionKey可以获取就绪Channel的集合,进行后续的I/O操作。


这里需要补充一下:NIO技术是依赖于操作系统内核实现的,JVM为跨平台实现创建了一个统一的抽象组,并且为不同操作系统进行具体实现,具体是java.nio.channels.spi包下面的SelectorProvider抽象类。这里主要方法有:

openDatagramChannel 创建和操作系统匹配的UDP通道实现。

openSelector 创建和操作系统匹配的选择器。

openServerSocketChannel 创建和操作系统匹配的服务器端通道。

openSocketChannel 创建和NIO 模型匹配的TCP socket套接字通道,用来反映客户端的TCP连接。

除此之外,nio还有java.nio.charset,这个跟字符的编解码有关。java.nio.file 有多种操作文件系统中文件方法,跟path结合使用。

这块的东西还是很多的,需要深入学习。

NIO优点:绕过了I/O在操作系统accept的阻塞问题,可以使操作系统在一个端口能同时受理多个客户端的I/O操作(端口数据接受规则只和选择器注册的关心事件有关)。

但是属于同步I/O模型,同步就是说:上层应用系统询问底层某个事件发生,底层不会主动告诉上层。

举例: 一个服务员,N份菜单,顾客拿菜单选好菜叫服务员,服务员可以记录多分点菜交给厨师。

四 异步I/O AIO

Java网络IO BIO NIO AIO_第4张图片

异步I/O采用订阅-通知模式,即程序向操作系统注册I/O监听,然后继续做自己的事。操作系统在I/O准备好后,主动推送程序,触发响应函数。异步的套接字通道时真正的异步非阻塞I/O,对应于UNIX网络编程中的事件驱动I/O(AIO)。他不需要过多的Selector对注册的通道进行轮询即可实现异步读写。

Java从jdk7开始,提供AIO支持。这部分内容被称作NIO.2,主要在java.nio.channels包下增加了下面四个异步通道:

  • AsynchronousSocketChannel
  • AsynchronousServerSocketChannel
  • AsynchronousFileChannel
  • AsynchronousDatagramChannel

其中的read/write方法,会返回一个带回调函数的对象,当执行完读取/写入操作后,直接调用回调函数。

Java网络IO BIO NIO AIO_第5张图片

同步和异步(操作系统级别)仅仅是关注的消息如何通知的机制,而阻塞与非阻塞(程序级别)关注的是程序请求操作系统I/o操作后,等待消息通知时,程序如何处理的状态。

这里实际应用更多的是NIO框架,就是netty了。

参考:https://blog.csdn.net/anxpp/article/details/51512200

你可能感兴趣的:(java)