1. I/O 简介

  I/O ( 输入/输出  ):指的是计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。

  在 Java 编程中,直到最近一直使用 流(Stream) 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接触。它也在内部使用,用于将对象转换为字节,然后再转换回对象。

  NIO 与原来的 I/O 有同样的作用和目的,但是它使用不同的方式: 块 I/O。块 I/O 的效率可以比流 I/O 高许多。

2. 阻塞IO与非阻塞IO:

Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。

Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。

2. IO(阻塞式IO):

假如现在你对阻塞I/O已有了一定了解,我们知道阻塞I/O在调用InputStream.read()方法时是阻塞的,它会一直等到数据到来时(或超时)才会返回;同样,在调用ServerSocket.accept()方法时,也会一直阻塞到有客户端连接才会返回,每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。阻塞I/O的通信模型示意图如下:

如果你细细分析,一定会发现阻塞I/O存在一些缺点。根据阻塞I/O通信模型,我总结了它的两点缺点:
(1)当客户端多时,会创建大量的处理线程。且每个线程都要占用栈空间和一些CPU时间。

(2)阻塞可能带来频繁的上下文切换,且大部分上下文切换可能是无意义的。

在这种情况下非阻塞式I/O就有了它的应用前景。

3. NIO(非阻塞式IO):

Java NIO是在jdk1.4开始使用的,它既可以说成" 新I/O ",也可以说成非阻塞式I/O。下面是java NIO的工作原理:
(1)由一个专门的线程来处理所有的 IO 事件,并负责分发。 
(2)事件驱动机制:事件到的时候触发,而不是同步的去监视事件。 
(3)线程通讯:线程之间通过 wait,notify 等方式通讯。保证每次上下文切换都是有意义的。减少无谓的线程切换。

阅读过一些资料之后,下面贴出我理解的java NIO的工作原理图: 

(注:每个线程的处理流程大概都是读取数据、解码、计算处理、编码、发送响应。)

Java NIO的服务端只需启动一个专门的线程来处理所有的 IO 事件,这种通信模型是怎么实现的呢?呵呵,我们一起来探究它的奥秘吧。java NIO采用了双向通道(channel)进行数据传输,而不是单向的流(stream),在通道上可以注册我们感兴趣的事件。一共有以下四种事件:

 

事件名 对应值
服务端接收客户端连接事件 SelectionKey.OP_ACCEPT(16)
客户端连接服务端事件 SelectionKey.OP_CONNECT(8)
读事件 SelectionKey.OP_READ(1)
写事件 SelectionKey.OP_WRITE(4)

服务端和客户端各自维护一个管理通道的对象,我们称之为selector,该对象能检测一个或多个通道 (channel) 上的事件。我们以服务端为例,如果服务端的selector上注册了读事件,某时刻客户端给服务端发送了一些数据,阻塞I/O这时会调用read()方法阻塞地读取数据,而NIO的服务端会在selector中添加一个读事件。服务端的处理线程会轮询地访问selector,如果访问selector时发现有感兴趣的事件到达,则处理这些事件,如果没有感兴趣的事件到达,则处理线程会一直阻塞直到感兴趣的事件到达为止。下面是我理解的java NIO的通信模型示意图:

4. NIO的(New IO流)简介

   JDK 1.4 中引入的新输入输出 (NIO) 库在标准 Java 代码中提供了高速的、面向块的 I/O。

   NIO 弥补了原来的 I/O 的不足。通过定义包含数据的类,以及通过以块的形式处理这些数据,NIO 不用使用本机代码就可以利用低级优化,这是原来的 I/O 包所无法做到的。

5. 为什么要使用 NIO?

NIO 的创建目的是为了让 Java 程序员可以实现高速 I/O 而无需编写自定义的本机代码。NIO 将最耗时的 I/O 操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。

 

Java基础知识强化之IO流笔记71:NIO之 NIO的(New IO流)介绍的更多相关文章

  1. Java基础知识强化之集合框架笔记71:模拟斗地主洗牌和发牌并对牌进行排序的案例

    1. 模拟斗地主洗牌和发牌并对牌进行排序的原理图解: 2. 代码实现: 思路: • 创建一个HashMap集合 • 创建一个ArrayList集合 • 创建花色数组和点数数组 • 从0开始往HashM ...

  2. Java基础知识强化之集合框架笔记76:ConcurrentHashMap之 ConcurrentHashMap简介

    1. ConcurrentHashMap简介: ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和Hashtable功能相同但是线程安全的方法.Conc ...

  3. Java基础知识强化之网络编程笔记14:TCP之多个客户端上传到一个服务器的思考(多线程改进)

    1. 多个客户端上传到一个服务器的思考 通过while循环可以改进一个服务器接收多个客户端. 但是这个是有问题的.如果是这种情况,假设我还有张三,李四,王五这三个人分别执行客户端  张三:好好学习.a ...

  4. Java基础知识强化之网络编程笔记13:TCP之TCP协议上传图片并给出反馈

    1. TCP协议上传图片并给出反馈: (1)客户端: package cn.itcast_13; import java.io.BufferedInputStream; import java.io. ...

  5. Java基础知识强化之网络编程笔记12:TCP之TCP协议上传文本文件并给出反馈

    1. 客户端: package cn.itcast_12; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...

  6. Java基础知识强化之网络编程笔记11:TCP之TCP协议上传文本文件

    1. TCP协议上传文本文件(客户端上传数据到服务器端) (1)客户端(上传数据到服务端) package cn.itcast_11; import java.io.BufferedReader; i ...

  7. Java基础知识强化之网络编程笔记10:TCP之客户端读取文本文件服务器控制台输出

    1. TCP之客户端读取文本文件服务器控制台输出 (1)客户端:(发送数据到服务端) package cn.itcast_10; import java.io.BufferedReader; impo ...

  8. Java基础知识强化之网络编程笔记08:TCP之客户端键盘录入服务器控制台输出

    1. 客户端: package cn.itcast_08; import java.io.BufferedReader; import java.io.BufferedWriter; import j ...

  9. Java基础知识强化之网络编程笔记23:Android网络通信之 Volley(Google开源网络通信库)

    联合网上资料学习:http://www.open-open.com/lib/view/open1451223702339.html 一.Volley的介绍 1. Volley简介 在这之前,我们在程序 ...

  10. Java基础知识强化之网络编程笔记22:Android网络通信之 Android常用OAuth登录(获取个人信息)

    1. 获取百度个人信息(使用Gson解析): 2. 代码案例: (1)工程一览图,如下: (2)activity_main.xml: <LinearLayout xmlns:android=&q ...

随机推荐

  1. 使用VS2010调用matlab的mat格式文件

    做实验需要将matlab实现的meanshift的结果中的region的Iabels矩阵,需要把labels.mat读入VS2010中,实现功能,在此把实现过程记录下来. C++读取mat文件的步骤如 ...

  2. 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回

    <深入Java虚拟机学习笔记>- 第19章 方法的调用与返回

  3. 【Jenkins】Linux搭建Jenkins平台

    为了配合上一篇的ant+jenkins做持续集成,需要在linux环境下搭建一个jenkins平台.网上有很多安装的例子,我主要记录一下自己遇到的问题,真真的是特别惆怅的,每次我遇到的问题都格外多. ...

  4. 设计模式_Interpreter_解释器模式

    形象例子: 俺有一个<泡MM真经>,上面有各种泡MM的攻略,比如说去吃西餐的步骤.去看电影的方法等等,跟MM约会时,只要做一个Interpreter,照着上面的脚本执行就可以了.解释器模式 ...

  5. 【转载】高性能I/O设计模式Reactor和Proactor

    转载自:http://blog.csdn.net/roger_77/article/details/1555170 昨天购买了<程序员>杂志 2007.4期,第一时间去翻阅了一遍,其中有一 ...

  6. hadoop面试题答案

    Hadoop 面试题,看看书找答案,看看你能答对多少(2) 1. 下面哪个程序负责 HDFS 数据存储.a)NameNode  b)Jobtracker  c)Datanode d)secondary ...

  7. Java中的IP对象以及本地域名解析

    本地域名解析操作步骤: 1.打开C:\WINDOWS\system32\drivers\etc目录 2.找到host文件,用记事本打开 3.添加“空间IP  域名” package WebProgra ...

  8. 教程-Python实例-发送邮件功能

    相关资料: http://www.cnblogs.com/xiaowuyi 实例代码: import smtplib from email.mime.text import MIMEText mail ...

  9. 虚方法(virtual)和抽象方法(abstract)的区别

    注:本文转载自 http://www.cnblogs.com/michaelxu/archive/2008/04/01/1132633.html 虚方法和抽象方法都可以供派生类重写,它们之间有什么区别 ...

  10. MySQL 约束

    MySQL中约束保存在information_schema数据库的table_constraints中,可以通过该表查询约束信息: 约束主要完成对数据的检验,保证数据库数据的完整性:如果有相互依赖数据 ...