博主自主知识产权《springboot深入浅出系列课程》(16章97节文档) 已经上线,请关注

java-NIO基础

java 字母哥 0评论

一、 Java NIO和传统IO的对比

比对项 传统IO NIO(Non-Block IO)
缓冲 面向流 面向块(缓冲)
IO模型 阻塞IO 非阻塞IO
线程复用 选择器

二、 java NIO类库简介

2.1 Buffer缓冲区(特点:面向块)

传统JavaIO是面向流的I/O。流I/O一次处理一个字节。NIO则是面向块的I/O,每次操作都是以数据块为单位。它们的差距就好象两个人吃饭,一个人一粒一粒的吃,另一个人狼吞虎咽,快慢显而易见。NIO中引入了缓冲区(Buffer)的概念,缓冲区作为传输数据的基本单位:块。Buffer缓冲区的引入,是NIO与传统IO的一个重要区别.在传统IO中,都是针对流数据的操作,在NIO中是针对缓冲区数据操作。
缓冲区的实质是一个数组,最常用的是ByteBuffer.事实上每一种java基本类型都对应一种缓冲区类型.
java-nio 缓冲区类图

2.2 Channel通道

Channel是数据通道,它与传统IO Stream的主要区别在于通道是双向读写的,流只是朝着一个方向移动
Channel可以主要分为2大类:一类为网络数据读写的SelectableChannel和文件读写的FileChannel.

2.3 多路复用器选择器Selector

Selector类是NIO的核心类,Selector能够检测多个注册的通道上,是否有事件发生,如果有事件发生,便获取事件然后针对每个事件进行相应的响应处理。这样一来,只是用一个单线程就可以管理多个通道,也就是管理多个连接。这样使得只有在连接真正有读写事件发生时,才会调用函数来进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程,并且避免了多线程之间的上下文切换导致的开销。

2.4 文件锁定,内存映射等其他新特性

  • 文件锁定是多个进程协同工作的情况下,要协调进程间对共享数据的访问必不可少的工具。
  • 内存映射利用虚拟内存技术提供对文件的高速缓存,使读取磁盘文件就像从内存中读取一样高效,但是却不会有内存泄漏的危险,因为在内存中不会存在文件的完整拷贝。

三、 IO模型

JDK4提供了非阻塞IO的能力,JDK7开始提供异步IO能力(NIO2.0)

3.1 阻塞I/O

  • 同步阻塞IO

在数据没有读写完成之前,线程不可以进行下一步操作,这样线程只好眼睁睁的在那里傻等。
下图为采用阻塞IO的通讯模型的服务端,由一个Acceptor监听客户端的链接,它接收到客户端的请求后创建一个新的线程进行链路处理,通过输出流应答客户端,线程销毁。简单地说就是,一客户端请求对应一个线程.
阻塞IO模型

这个模型有一个很大的问题,就是当客户端请求规模较大的时候,一客户端请求创建一个线程,导致服务器资源消耗殆尽,造成宕机。

  • 伪异步IO(线程池)

为了解决这个问题,在服务端使用线程池。线程的数量是固定的(线程池),使用的时候借用获取,用完之后不是销毁而是将线程归还给线程池。但这个解决方案,在并发量超过线程池内现成的数量时,会导致获取线程的时间拉长,应答缓慢,延迟较大!这个方案,我们称为"伪异步IO"!
伪异步IO模型

3.2 非阻塞I/O(Non-Block IO)

  • 传统JavaIO是基于阻塞I/O模型的:当发起一个I/O请求时,如果数据没有准备好(read时无可读数据,write时数据不可写入),那么线程便会阻塞,直到数据准备好,导致线程大部分的时间都在阻塞。
  • 非阻塞I/O则允许线程在有数据的时候处理数据,没有数据的时候释放CPU资源,提高了资源利用率。在数据没有准备好之前,调用线程可以离开,只需要每隔一段时间回来询问一次。

3.3 异步I/O

在数据没有读写完成之前,调用线程可以离开也不用轮询。在数据准备好之后,多路复用监听会主动通知调用线程。这通常需要复杂的设计,为降低NIO与AIO的实现复杂度,我们可以使用Netty或者mina等框架。

java-io模型对比

喜欢 (9)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址