我们作为开发的,很多底层东西都需要了解一点,因为万一自己有机会去开发框架而不是单单的写业务了呢。而我就是在慢慢的摸索中。关于IO的东西,我也是看看视频,自己敲敲代码,然后就来这里记一下笔记。
先说一下几个个人理解的概念吧,阻塞和非阻塞(BIO对比NIO):线程访问数据时,数据是需要准备时间的,特别是io读取,因为用户态和内核态的切换以及数据的解析读取都是很慢的,所以才会有阻塞的情况。阻塞就是数据没有准备好的时候,一定停滞不前,等到数据完全准备好才进行下一步的操作。而非阻塞就是数据没有准备好,那我就返回做自己其他的事,等到准备好了再回来执行,那么这里就有一个通知问题。NIO就是通过多路复用选择器无限循环(轮询)获取数据的完成情况来做到的。(linux的selector模式)。
同步和异步(BIO、NIO对比AIO):这两个概念是基于应用程序和操作系统处理IO时间锁采用的方法。同步就是直接参与,数据完成之后才返回,这样会阻塞在一个方法上面(所以BIO和NIO都是会阻塞的,只是BIO阻塞就一直等待,NIO阻塞,可以通过选择器继续下次的io,他们两个其实调用read方法都是阻塞的)。异步就是遇到IO直接让操作系统去做(linux的epoll模式),自己等着通知就可以了。
BIO,每次请求过来,都必须开一个线程,因为你不知道这个任务需要读取多少东西,或者根据不想读取,就是请求连接,然后一直等着客户端的输入。这样就会出现很多无用的线程,但是因为客户端的输入或者不作为,这些线程还不能shutdown,这样任务多了对于服务端就是线程爆炸,拖慢所有的线程。
NIO,每次请求过来,都会在selector上面注册一个信息,然后selector循环遍历这些信息,遇到读写的情况才会通知操作系统去处理IO事件,这样就可以省下很多无用的线程。
对比:感觉NIO很优是不是,是的。但是BIO就一无是处了吗?不是,如果遇到所有的连接都是IO读写,而且都是大任务(就是读和写都花费很长的时间),这样的情况下,NIO也没有什么优势,反而会因为多了选择器,拖慢了总体的进度,而且NIO是基于bufferr缓存的,也就是每次读取一个缓存,这样可能会出现读取半个数据,这样对于解析来说就复杂很多。这时候BIO反而会好很多。所以NIO最适用的就是请求数据量不大的情况下,如果每次都是例如文件下载的方式,BIO效果更好。
AIO,每次请求过来,我们只需要通知操作系统去做IO,用户线程不参与进去,操作系统读取完成通知用户线程,这时候再去处理,同样是基于缓存的。
其实这些概念说的都很乏味,还不如直接上代码,我也手写了BIO和AIO客户端和服务端的一些代码,每一行都有注释。
对于这些东西,必须自己动手敲一遍,不然用户都只是停留在概念,然后看了忘,留下不了什么,必须,必须,必须自己动手。
代码好像不能上传简书,我只好上传自己的github了。。。尴尬https://github.com/1581501186/BaseInterfaceWithNoImpl