/**
* NIO非阻塞式编程<p>
* 服务端和客户端各自维护一个管理通道的对象,我们称之为selector,该对象能检测一个或多个通道 (channel) 上的事件。
* 我们以服务端为例,如果服务端的selector上注册了读事件,某时刻客户端给服务端发送了一些数据,阻塞I/O这时会调用read()方法阻塞地读取数据,而NIO的服务端会在selector中添加一个读事件。
* 服务端的处理线程会轮询地访问selector,如果访问selector时发现有感兴趣的事件到达,则处理这些事件,如果没有感兴趣的事件到达,则处理线程会一直阻塞直到感兴趣的事件到达为止。
* 下面是我理解的java NIO的通信模型示意图:
* (一)
* IO和NIO,NIO并不比传统IO快,而是在高并发场景下能够有效减少thread数,从而提供CPU的利用率。
* 原因为:传统的IO在accept到一个socket后,一个线程会负责这个socket的读写,如果这个过程中数据还没有准备完毕这个线程会一直等待直到数据处理完或超时。
* NIO采用的是selector方式,accept到一个socketChannel后,会将这个socketChannel注册到seletor名下,这个时候并不需要worker线程,当读写的数据准备好时seletor会有响应的事件产生,
* 此刻再将这个socketChannel丢给一个worker线程,既然数据都准备好了,worker线程就不需要等待直需要做相应的业务逻辑。
* 从上面的分析可知,在高并发环境下,传统IO需要更多的worker线程(数据准备等待的开销都在它上面), 而NIO确是直接读写数据就好了,没有什么等待,所以worker线程数相对较小。
优化:大量小数据网络读写会消耗很多的CPU,优化方法可以有:减少网络调用(合并数据,压缩),使用NIO减少线程数,线程越多维护的开销就越大。
<br>
NIO支持操作系统特性包括:文件锁定、非阻塞I/O、就绪性选择、和内存映射。当今操作系统大都支持这些特性
<h2>为什么要使用NIO?</h2>

  对于文件I/O, 在我看来使用IO和NIO是区别不大的,Java1.4开始原始IO也根据NIO重新实现过了,提供了对于NIO特性的支持。即使是流,也会比以前更加高效。
企业级应用软件中涉及I/O的部分多半是读写文件的功能性需求,很少有在并发上的要求,那么JavaIO包已经很胜任了。

  对于网络I/O,传统的阻塞式I/O,一个线程对应一个连接,采用线程池的模式在大部分场景下简单高效。当连接数茫茫多时,并且数据的移动非常频繁,NIO无疑是更好的选择。

  NIO标榜的是高速、可伸缩的I/O,因为它更亲近操作系统。当需求很平凡,没有太高的效率要求的时候,你看不出它的好,反而觉得NIO代码实现复杂,不易理解。选择与否全看使用的场景,
这点就看使用者的权衡了。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
(二)
(1)面向块的I/O

  传统JavaIO是面向流的I/O。流I/O一次处理一个字节。NIO则是面向块的I/O,每次操作都是以数据块为单位。它们的差距就好象两个人吃饭,一个人一粒一粒的吃,另一个人狼吞虎咽,快慢显而易见。

  NIO中引入了缓冲区(Buffer)的概念,缓冲区作为传输数据的基本单位块,所有对数据的操作都是基于将数据移进/移出缓冲区而来;读数据的时候从缓冲区中取,写的时候将数据填入缓冲区。尽管传统JavaIO中也有相应的缓冲区过滤器流(BufferedInputStream等),但是移进/移出的操作是由程序员来包装的,它本质是对数据结构化和积累达到处理时的方便,并不是一种提高I/O效率的措施。NIO的缓冲区则不然,对缓冲区的移进/移出操作是由底层操作系统来实现的。

  通常一次缓冲区操作是这样的:某个进程需要进行I/O操作,它执行了一次读(read)或者写(write)的系统调用,向底层操作系统发出了请求,操作系统会按要求把数据缓冲区填满或者排干。说起来简单,其实很复杂。但至少我们知道了这事是由操作系统干的,比我们代码级的实现要高效的多。

  除了效率上的差别外,缓冲区在数据分析和处理上也带来的很大的便利和灵活性。

(2)非阻塞的I/O + 就绪性选择

  传统JavaIO是基于阻塞I/O模型的:当发起一个I/O请求时,如果数据没有准备好(read时无可读数据,write时数据不可写入),那么线程便会阻塞,直到数据准备好,导致线程大部分的时间都在阻塞。

  而非阻塞I/O则允许线程在有数据的时候处理数据,没有数据的时候干点别的,提高了资源利用率。

  就绪性选择通常是建立在非阻塞的基础上,并且更进一步,它把检查哪些I/O请求的数据准备好这个任务交给了底层操作系统,操作系统会去查看并返回结果集合,这样我们只需要关心那些准备好进行操作的IO通道。关于就绪性选择的过程会在后面详述。

  NIO提供的Socket可以用非阻塞的方式工作,并且支持就绪性选择,减少了资源消耗和CPU在线程间的切换,在管理线程效率上比传统Socket高。
(3)文件锁定和内存映射文件等操作系统特性

  NIO同时带来了很多当今操作系统大都支持的特性。

  文件锁定是多个进程协同工作的情况下,要协调进程间对共享数据的访问必不可少的工具。

  内存映射利用虚拟内存技术提供对文件的高速缓存,使读取磁盘文件就像从内存中读取一样高效,但是却不会有内存泄漏的危险,因为在内存中不会存在文件的完整拷贝。

  此外还有一些其他的特性,后面再详述。

NIO非阻塞式编程的更多相关文章

  1. Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程

    Socket-IO 系列(三)基于 NIO 的同步非阻塞式编程 缓冲区(Buffer) 用于存储数据 通道(Channel) 用于传输数据 多路复用器(Selector) 用于轮询 Channel 状 ...

  2. Java基础——NIO(二)非阻塞式网络通信与NIO2新增类库

    一.NIO非阻塞式网络通信 1.阻塞与非阻塞的概念  传统的 IO 流都是阻塞式的.也就是说,当一个线程调用 read() 或 write() 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在 ...

  3. Swing做的非阻塞式仿飞秋聊天程序

    采用Swing 布局 NIO非阻塞式仿飞秋聊天程序, 切换皮肤颜色什么的小功能以后慢慢做 启动主程序. 当用户打开主程序后自动获取局域网段IP可以在 设置 --> IP网段过滤, 拥有 JMF ...

  4. Java IO(3)非阻塞式输入输出(NIO)

    在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...

  5. Linux NIO 系列(03) 非阻塞式 IO

    目录 一.非阻塞式 IO 附:非阻塞式 IO 编程 Linux NIO 系列(03) 非阻塞式 IO Netty 系列目录(https://www.cnblogs.com/binarylei/p/10 ...

  6. java socket编程开发简单例子 与 nio非阻塞通道

    基本socket编程 1.以下只是简单例子,没有用多线程处理,只能一发一收(由于scan.nextLine()线程会进入等待状态),使用时可以根据具体项目功能进行优化处理 2.以下代码使用了1.8新特 ...

  7. 4.NIO的非阻塞式网络通信

    /*阻塞 和 非阻塞 是对于 网络通信而言的*/ /*原先IO通信在进行一些读写操作 或者 等待 客户机连接 这种,是阻塞的,必须要等到有数据被处理,当前线程才被释放*/ /*NIO 通信 是将这个阻 ...

  8. 基于NIO写的阻塞式和非阻塞式的客户端服务端

    由于功能太过简单,就不过多阐述了,直接上阻塞式代码: package com.lql.nio; import org.junit.Test; import java.io.IOException; i ...

  9. NIO 的非阻塞式网络通信

    1.阻塞与非阻塞   ①  传统的 IO 流都是阻塞式的.也就是说,当一个线程调用 read() 或 write()时, 该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务. 因 ...

随机推荐

  1. 20190712_mysql执行sql脚本语句_Failed to open file_error

    要说执行sql脚本语句不难 就下面这条语句: 进入mysql安装目录下的bin目录 然后执行: \mysql –u用户名 –p密码 –D数据库<[sql脚本文件路径全名] 比如: C:\MySQ ...

  2. Mac用brew更新完python2.7后无法找到虚拟环境

    Mac下virtualenv遇到dyld: Library not loaded: @executable_path/../.Python Referenced ...问题的解决措施 find ~/. ...

  3. lcm的和(莫比乌斯反演)

    马上开学了,加一个操作系统和数据库标签 不玩了,求1-n和1-m的lcm(i,j)和 首先想到把lcm(i,j)转化为i * j / gcd(i, j) 然后gcd,要素察觉,开始枚举d使得gcd(i ...

  4. 记一次MySQL出现Waiting for table metadata lock的原因、排查过程与解决方法

    任务背景:将sql文件通过shell直接导入到mysql中执行(还原) bug表现:导入后java项目卡死 过程: 1.网上乱搜一通,无意间看到一篇文章,这篇文章说明了如何开启mysql的genera ...

  5. moviepy音视频开发:audio_loop实现音频内容循环重复

    ☞ ░ 前往老猿Python博文目录 ░ 概述 moviepy的audio_loop函数用于将音频剪辑内容循环一定次数,返回值是原剪辑内容重复指定次数对应的剪辑. 调用语法: audio_loop(a ...

  6. PyQt(Python+Qt)学习随笔:QTreeWidget树型部件中的QTreeWidgetItem项构造方法

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTreeWidget树型部件的项是单独的类对象,这个类就是QTreeWidgetItem. QTr ...

  7. PyQt(Python+Qt)学习随笔:Qt Designer中部件的mouseTracking和tabletTracking属性

    在Qt Designer中的部件属性设置中,有mouseTracking和tabletTracking两个属性,这两个属性是跟踪鼠标或平板触控笔的移动轨迹的. 一.mouseTracking mous ...

  8. PHP代码审计分段讲解(2)

    03 多重加密 源代码为: <?php include 'common.php'; $requset = array_merge($_GET, $_POST, $_SESSION, $_COOK ...

  9. protobuf 协议浅析

    目录 Protobuf 协议浅析 1. Protobuf 介绍 1.1 Protobuf 基本概念 1.2 Protobuf 的优点 1.3 Protobuf, JSON, XML 的区别 2. Pr ...

  10. ubuntu18.04 登录界面循环,已解决

    按照百度的方法,要卸载重装nvidia,遇到如下问题 1.进入Ubuntu字符界面,出现乱码,猜测是sudo命令出现问题,果然 解决方案:$ PATH=/usr/kerberos/sbin:/usr/ ...