如何理解NIO

文章目录

    • 1.什么是NIO?
    • 2.为什么用NIO,传统IO有什么缺陷?
    • 3.NIO和IO的区别
    • 4.怎么理解NIO是面向块的、非阻塞的
    • 5.NIO是怎么实现的?

1.什么是NIO?

java.nio全称java non-blocking IO(实际上是 new io),是指JDK 1.4 及以上版本里提供的新api(New IO) ,为所有的原始类型(boolean类型除外)提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络。

2.为什么用NIO,传统IO有什么缺陷?

一个使用传统阻塞I/O的系统,如果还是使用传统的一个请求对应一个线程这种模式,一旦有高并发的大量请求,就会有如下问题:

1、线程不够用, 就算使用了线程池复用线程也无济于事;
2、阻塞I/O模式下,会有大量的线程被阻塞,一直在等待数据,这个时候的线程被挂起,只能干等,CPU利用率很低,换句话说,系统的吞吐量差;
3、如果网络I/O堵塞或者有网络抖动或者网络故障等,线程的阻塞时间可能很长。整个系统也变的不可靠

最直接的体现在于服务器与客户端进行通讯时,每加入一台客户端需要一个IO线程阻塞等待对方数据传送,会导致服务器不断开启线程,但这些线程大部分时间都是阻塞在那里,浪费资源,并且支持不了大并发。

3.NIO和IO的区别

原有的 IO 是面向流的、阻塞的,NIO 则是面向块的、非阻塞的

原始的IO是面向流的,不存在缓存的概念。Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区
Java IO的各种流是阻塞的,这意味着当一个线程调用read或 write方法时,该线程被阻塞,直到有一些数据被读取,或数据完全写入,该线程在此期间不能再干任何事情了。

4.怎么理解NIO是面向块的、非阻塞的

NIO是面向缓冲区的。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性。
Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。
通俗理解:NIO是可以做到用一个线程来处理多个操作的。假设有10000个请求过来,根据实际情况,可以分配50或者100个线程来处理。不像之前的阻塞IO那样,非得分配10000个。

5.NIO是怎么实现的?

1.buffer 缓存数组

缓冲区本质上是一个可以写入数据的内存块,然后可以再次读取,该对象提供了一组方法,可以更轻松地使用内存块,使用缓冲区读取和写入数据通常遵循以下四个步骤:

  1. 写数据到缓冲区;
  2. 调用buffer.flip()方法;
  3. 从缓冲区中读取数据;
  4. 调用buffer.clear()或buffer.compat()方法;

当向buffer写入数据时,buffer会记录下写了多少数据,一旦要读取数据,需要通过flip()方法将Buffer从写模式切换到读模式,在读模式下可以读取之前写入到buffer的所有数据,一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。

三个重要概念(参数)

a.容量(capacity)

b.界限(limit)

c.位置(position)

在这里插入图片描述
缓冲区常用的操作
向缓冲区写数据:

  1. 从Channel写到Buffer;
  2. 通过Buffer的put方法写到Buffer中;
    从缓冲区读取数据:
  3. 从Buffer中读取数据到Channel;
  4. 通过Buffer的get方法从Buffer中读取数据;
    flip方法:
    将Buffer从写模式切换到读模式,将position值重置为0,limit的值设置为之前position的值;
    clear方法 vs compact方法:
    clear方法清空缓冲区;compact方法只会清空已读取的数据,而还未读取的数据继续保存在Buffer中;

2.channel

a. 通道可以同时进行读写,而流只能读或者只能写

b. 通道可以实现异步读写数据

c. 通道可以从缓冲读数据,也可以写数据到缓冲:

channel提供了一个map()方法,可以直接将数据映射到内存中。
在这里插入图片描述

3.Selector(选择器)

可以检测多个NIO channel,看看读或者写事件是否就绪。

多个Channel以事件的方式可以注册到同一个Selector,从而达到用一个线程处理多个请求成为可能。

在这里插入图片描述

selector的创建

通过调用Selector.open()方法创建一个Selector对象

注册Channel到Selector

channel.configureBlocking(false);

channel.register(selector, Selectionkey.OP_READ);

注:Channel必须是非阻塞的。

所以FileChannel不适用Selector,因为FileChannel不能切换为非阻塞模式,更准确的来说是因为FileChannel没有继承SelectableChannel。Socket channel可以正常使用。

register() 方法的第二个参数。这是一个“ interest集合 ”,意思是在通过Selector监听Channel时对什么事件感兴趣。可以监听四种不同类型的事件:

  • Connect
  • Accept
  • Read
  • Write

SelectionKey介绍
一个SelectionKey键表示了一个特定的通道对象和一个特定的选择器对象之间的注册关系。
key.attachment(); //返回SelectionKey的attachment,attachment可以在注册channel的时候指定。
key.channel(); // 返回该SelectionKey对应的channel。
key.selector(); // 返回该SelectionKey对应的Selector。
key.interestOps(); //返回代表需要Selector监控的IO操作的bit mask
key.readyOps(); // 返回一个bit mask,代表在相应channel上可以进行的IO操作。

理解

传统IO在读写过程中是不允许停止的需要一直占用线程,对于一个一直有内容可读的文件不用切换线程这样效率的确不错,但是对于网络通讯中网络传输的并发需要不停开启新的线程并且对于计算机而言,它的大部分时间都是阻塞的,所以对于这种情况我们就对它进行了改写使用NIO非阻塞式的IO。

非阻塞式的IO,将内容写到一个Buffer中通过操作Bufer的标识(或者说游标),来改变其读或者写的状态,将它变成了分块的模式,通过通道channel进行数据传递,对内存中内容进行映射,读完了就结束,不需要一直占用线程。然而对于channel要有标识需要知道每个channel对应的谁写的谁读的问题,于是就有了Selector,通过regiser注册每个channel这样就可以知道哪个channel读好了,写完了的过程,执行其他的操作,每个channel不是单独的占用线程.这样就更好的支持了并发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/557559.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

sublime php快捷键,分享Sublime Text 3快捷键精华版!

下面由sublime教程栏目给大家介绍Sublime Text 3 快捷键精华版,希望对需要的朋友有所帮助!CtrlShiftP:打开命令面板CtrlP:搜索项目中的文件CtrlG:跳转到第几行CtrlW:关闭当前打开文件CtrlShiftW&#xff1a…

MyBatis Plus——忽略某个实体类属性和数据库表字段之间的映射关系

问题描述 在开发中可能会遇到MyBatis-Plus使用实体类属性进行SQL操作,但是不用存到数据库中去查找,这时候我们的实体中有这个属性,但是数据库的表中没有这个字段(即:实体类属性非数据库表字段),如果不做处理就会报错。…

php 高德地图计算距离,距离、长度、面积

JS API 为开发者提供了空间数据计算的函数库 AMap.GeometryUtil,可以帮助开发者计算点线面空间关系、长度、面积等函数。更多示例请查看 示例中心本章我们将介绍一些常用的数学计算方法,包括:计算两点间的实际距离 AMap.GeometryUtil.distanc…

@Transient注解作用

java 的transient关键字的作用是需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。 用法 transient 就是在给某个javabean上需要添加个属性,但是这…

Java隐含对象实验报告,JSP隐含对象response实现文件下载

一.简单介绍JSP隐含对象response实现文件下载(1)在JSP中实现文件下载最简单的方法是定义超链接指向目标资源,用户单击超链接后直接下载资源,但直接暴露资源的URL也会带来一些负面的影响,例如容易被其它网站盗链,造成本地服务器下载…

JDBC中使用preparedStatement防止SQL注入

一、SQL注入 SQL注入是一种比较常见的网路攻击方式,一些恶意人员在需要用户输入的地方,恶意输入SQL语句的片段,通过SQL语句,实现无账号登录,甚至篡改数据库。 二、SQL注入实例 登录场景: 在一个登录界面…

Java预科篇1-学前

Java预科篇1-学前 1、markdown语法 Markdown是一种纯文本格式的标记语言。通过简单的标记语法,它可以使普通文本内容具有一定的格式。 优点: 因为是纯文本,所以只要支持Markdown的地方都能获得一样的编辑效果,可以让作者摆脱排…

Java预科篇2-环境搭建

Java预科篇2-环境搭建 1、Java历史 1995年 Java问世1996年 Java 1.01999年 Java 1.2发布(JAVA SE\JAVA EE\JAVA ME)… … …2004年 Tiger 发布(JAVA5.0),Java 登录火星2011年 7月由Oracle正式发布Java7.02014年 3月19日,Oracle公…

php中如何配置环境变量,如何配置phpstorm环境变量如何配置phpstorm环境变量

大话西游6664版。根据你的系统平台下载相应的版本后,如果是压缩文件,先解压后双击运行,不是压缩文件,直接双击运行就可以了,运行后出现下面的界面,在下面界面上单击“Next”。跟所有的软件安装包一样&#…

Java基础篇1——变量与数据类型

Java基础篇1——变量与数据类型 1、标识符命名规则 标识符以由大小写字母、数字、下划线(_)和美元符号($)组成,但是不能以数字开头。大小写敏感不能与Java语言的关键字重名不能和Java类库的类名重名不能有空格、、#、、-、/ 等符号长度无限制应该使用有意义的名称…

php伪静态后301,动态地址rewrite伪静态,然后301跳转到伪静态时死

本文章来给各位同学介绍动态地址rewrite伪静态,然后301跳转到伪静态时死循环解决办法,有碰到此类的朋友可进入参考。问题背景:矿秘书网的历史遗留问题,刚开始由于各种问题,一些动态页面都是用了?id参数的形式&#xf…

Java基础篇2——运算符

Java基础篇2——运算符 1、运算符 1.1、算数运算符 表示加法运算符-表示减法运算符*表示乘法运算符/表示除法运算符%表示取余运算符 1.2、关系运算符 所有以关系运算符作为最终运算的表达式结果一定是boolean类型 >表示是否大于运算符>表示是否大于等于运算符<表…

php 移植 arm 精简,arm linux 移植 PHP

背景&#xff1a;PHP 是世界上最好的语言&#xff0c;所以要考虑php的移植。host平台   &#xff1a;Ubuntu 16.04arm平台   &#xff1a; 3531darm-gcc   &#xff1a;4.9.4主机准备&#xff1a;使用以下脚本### Copyright By Schips, All Rights Reserved# https://git…

Java基础篇3——流程控制

Java基础篇3——流程控制 1、顺序结构 正常代码的流程即是顺序流程 2、分支结构 2.1、if-else分支 if(条件表达式) {语句块1; }if(条件表达式) {语句块1; } else {语句块2; }if(条件表达式1) {语句块1; } else if(条件表达式2) {语句块2; } else {语句块3; }2.2、switc…

hive mysql类型,(二)Hive数据类型、数据定义、数据操作和查询

1.数据类型1.1 基本数据类型Hive数据类型长度例子TINYINT1byte有符号整数20SMALINT2byte有符号整数20INT4byte有符号整数20BIGINT8byte有符号整数20BOOLEAN布尔类型&#xff0c;true或者falseTRUE FALSEFLOAT单精度浮点数3.14159DOUBLE双精度浮点数3.14159STRING字符系列。可以…

Error running tomcat8 Address localhost:1099 is already in use 错误解决

错误情况&#xff1a; 在IDEA上运行web项目时报错&#xff1a;Error running &#xff08;项目名&#xff09; Address localhost:1099 is already in use 解决方法&#xff1a; 第一步&#xff1a;打开Windows运行&#xff0c;如下图 第二步&#xff1a;按下回车或点击确定…

matlab数据处理 书,matlab数据处理记录

最近在看一篇论文&#xff0c;觉得文章的数据处理效果十分的惊艳&#xff01;所以想着如何用matlab将类似的效果实现出来&#xff0c;但最近有一个任务&#xff0c;以后慢慢更新吧&#xff01;先挖一个坑&#xff01;1. 二维图形绘制二维坐标轴图像涉及的部分包含曲线的颜色、点…

StringUtils系列之StringUtils.isNotBlank()和StringUtils.isNotBlank()的区别

/** 1.* StringUtils.isNotBlank();* 判断参数是否不为空.* 1.如果不为空返回true。* 2.如果为空返回false。* StringUtils.isNotEmpty(null) -> false* StringUtils.isNotEmpty("") -> false* StringUtils.isNotEmpty("a") -> true* StringUti…

matlab信号内插,基于VC++和Matlab的数字信号内插处理系统

0引言目前,利用并行交替式(Parallalinterleaving)技术,超高速数字化示波器的实时采样速率已突破了10Gsa/s。按照Nyquist定理,这种系统的实时带宽可接近5GHz。在数字化示波器中,由实时采样获得的样本数据原封不动地显示时,因采样理论和显示技术等缘故,可能会产生不同形式的视觉混…

MySQL-locate()函数

判断字符串&#xff08;string&#xff09;中是否包含另一个字符串&#xff08;subStr&#xff09;locate(subStr,string) &#xff1a;函数返回subStr在string中出现的位置 // 如果字符串 string 包含 subStr locate(subStr,string) > 0// 如果字符串 string 不包含 subSt…