谈谈我对java的BIO和NIO的学习的理解

首先io是人机交互的前提 是非常重要滴

java在早期只有bio 后面更新出来了nio nio的作用越来越重要

有的人称nio为阻塞式io 这点我觉得很不严谨 而且对于阻塞与非阻塞的概念我看很多人的说法也不一致

在此我只说说我自己的认识 毕竟认知也是一个不断提升和完善的过程 就像地球由方到圆一样

 

io又分为磁盘io 和网络io

 

首先传统io是"单个"  nio是"多个"

从磁盘io来说

所谓的单个和多个怎么理解呢  单个就是stream 多个就是buffer  你可以想象从磁盘读取文件就像是一根吸管吸,而通过buffer和channel来读取磁盘文件你可以认为你有一个可以调节大小的勺子 你可以设置你每次装到勺子里的水的数量 然后一次性把勺子里的水拿过来 这两种方式都是阻塞式io 就是他们都需要去等待操作系统把数据从磁盘读取到内核地址空间(至于内核地址空间和用户地地址空间百度一下) 然后去完成这个copy的过程   记住阻塞的时间计算是从程序执行到要读取或者写入数据的这一行代码时候 ,然后从系统执行read执行 读取磁盘数据到内核空间 到完成copy 到用户空间  当代码真正执行 copy之前都是属于等待阶端 线程会被阻塞不运行从而cpu的利用率就被浪费了 这样基于stream的io和基于buffer的io 执行效率上并没有什么大的差异     

但是nio在本地的磁盘io中有一种内存映射的方式 他可以把内核地址空间和用户地址空间中的一块你要操作的数据直接映射到一块内存空间上 这样你直接对该内存区域就可以进行数据的访问和输入操作 从而省去了copy的过程大大提升了响应的速度(记住是响应的速度不是io的速度) 但是这样也有一个弊端 就是这块内存区域的回收管理会不稳定 已经超出了jvm的掌控 所以jvm会出现内存泄漏的情况 真正使用看情况而定 如果是大文件并且频繁进行操作的话就可以使用这种内存映射的方式 可能有人会说这种方式的nio是不是非阻塞式io 我认为不是   参照我上面的认知 凡是在执行copy操作之前他的等待都是阻塞 而这里他内存映射之后需要由操作系统将数据读取到内核空间 这段时间线程也需要等待 所以我认为他还是阻塞式io 但是速度的提升很大 因为少了copy的过程嘛

简而言之 磁盘io都是阻塞式io 至少目前我的认知是这样的

从网络io来说传统的javaio是基于socket来实现而nio是基于socketchannel来实现的 有什么区别呢? 传统的socket进行网络数据的传输是通过steam来实现的 一旦在等待一个连接或者是接收请求的时候都会等待数据就绪的这个时间进行阻塞 这就这样如果同时有多个连接的话效率就非常低下 但是我们可以通过多线程来解决 创建线程就会非常消耗性能 所以我们通过线程池来进行解决 但是如果有长连接的话 就无法很好的解决了

但是基于nio的网络io我们可以配置为非阻塞 然后通过一个selector来将每个通道注册到选择器上 这样只有每个数据就绪以后才会触发一个事件来通知线程进行操作 所以就省去了我们线程阻塞等待的时间 只需要数据就绪以后我们再进行操作这样在原来的阻塞的时间就可以让线程一直运行去处理其他通道触发的事件 这样我们就可以通过一个线程来处理多个连接请求大大提高了cpu的利用率 这种轮询的方式让线程一直处于忙碌的状态,将原来阻塞等待的时间充分利用起来去做别的事情 这就是nio好的地方

你可能感兴趣的:(谈谈我对java的BIO和NIO的学习的理解)