第11讲 | Java提供了哪些IO方式? NIO如何实现多路复用?
该思维导图由 AI 生成,仅供参考
典型回答
- 深入了解
- 翻译
- 解释
- 总结
Java的IO机制经历了传统同步IO和较新的NIO框架的发展,为读者提供了更多可能性。传统的java.io包提供了熟知的IO功能,但在处理大规模数据和分布式系统时存在局限性。相比之下,NIO框架引入了Channel、Selector、Buffer等新的抽象,可以构建多路复用的、同步非阻塞IO程序,提供了更接近操作系统底层的高性能数据操作方式。在Java 7中,NIO有了进一步的改进,引入了异步非阻塞IO方式,也称为AIO,实现了应用操作的非阻塞处理。NIO的主要组成部分包括Buffer、Channel、Selector和Charset,它们提供了高效的数据容器、底层抽象和编解码器等功能。NIO通过多路复用机制解决了同步阻塞方式的低扩展性问题,提高了应用的扩展能力。相比之下,AIO引入了异步IO模式,利用事件和回调处理操作,进一步提升了IO处理的效率。通过比较传统IO和NIO的实现方式,以及NIO在处理大规模数据和高并发情况下的优势,读者可以更直观地了解Java IO机制的发展和应用。同时,通过示例代码和场景分析,读者可以更好地了解NIO和AIO的工作原理和优势,为他们在实际应用中选择合适的IO方式提供了参考。文章通过深入浅出的方式介绍了Java IO机制的发展和特点,为读者提供了全面的了解和实际应用的指导。
《Java 核心技术面试精讲》,新⼈⾸单¥59
全部留言(74)
- 最新
- 精选
- 雷霹雳的爸爸批评NIO确实要小心,我觉得主要是三方面,首先是如果是从写BIO过来的同学,需要有一个巨大的观念上的转变,要清楚网络就是并非时刻可读可写,我们用NIO就是在认真的面对这个问题,别把channel当流往死里用,没读出来写不进去的时候,就是该考虑让度线程资源了,第二点是NIO在不同的平台上的实现方式是不一样的,如果你工作用电脑是win,生产是linux,那么建议直接在linux上调试和测试,第三点,概念上的,理解了会在各方面都有益处,NIO在IO操作本身上还是阻塞的,也就是他还是同步IO,AIO读写行为的回调才是异步IO,而这个真正实现,还是看系统底层的,写完之后,我觉得我这一二三有点凑数的嫌疑
作者回复: 不错,不过,在非常有必要之前,不见得都要底层,毕竟各种抽象,都是为特定领域工程师准备的,JMM等抽象都是为了大家有个清晰的、不同层面的高效交流
2018-05-2957 - Chan忘记回答问题了。所以对于多路复用IO,当出现有的IO请求在数据拷贝阶段,会出现由于资源类型过份庞大而导致线程长期阻塞,最后造成性能瓶颈的情况
作者回复: 对
2018-06-16238 - 扁担据我理解,NIO2的局限性在于,如果回调时客户端做了重操作,就会影响调度,导致后续的client回调缓慢
作者回复: 对,这是这种多路复用的主要局限之一,nodejs等其他类似框架都有这问题
2018-10-21318 - 扁扁圆圆这里Nio的Selector只注册了一个sever chanel,这没有实现多路复用吧,多路复用不是注册了多个channel ,处理就绪的吗?而且处理客户端请求也是在同线程内,这还不如上面给的Bio解决方案吧
作者回复: 这是简化的例子,少占篇幅
2018-06-02211 - yxwjava nio的selector主要的问题是效率,当并发连接数达到数万甚至数十万的时候 ,单线程的selector会是一个瓶颈;另一个问题就是再线上运行过程中经常出现cpu占用100%的情况,原因也是由于selector依赖的操作系统底层机制bug 导致的selector假死,需要程序重建selector来解决,这个问题再jdk中似乎并没有很好的解决,netty成为了线上更加可靠的网络框架。不知理解的是否正确,请老师指教。
作者回复: 嗯,有局限性;那个epoll的bug应该在8里修了,netty的改进不止那些,它为了性能改了很多底层,后面会介绍,好多算是hack;另外nio的目的是通用场景的基础API,和终端应用有个距离,核心类库很多都是如此定位,netty这种开源框架更贴近用户场景
2018-06-039 - zjh看nio代码部分,请求接受和处理都是一个线程在做。这样的话,如果有多个请求过来都是按顺序处理吧,其中一个处理时间比较耗时的话那所有请求不都卡住了吗?如果把nio的处理部分也改成多线程会有什么问题吗
作者回复: 这种情况需要考虑把耗时操作并发处理,再说处理是费cpu,还是重io,需要不同处理;如果耗时操作非常多,就不符合这种模型的适用场景
2018-05-319 - lorancechen我也自己写过一个基于nio2的网络程序,觉得配合futrue写起来很舒服。 仓库地址:https://github.com/LoranceChen/RxSocket 欢迎相互交流开发经验~ 记得在netty中,有一个搁置的netty5.x项目被废弃掉了,原因有一点官方说是性能提升不明显,这是可以理解的,因为linux下是基于epoll,本质还是select操作。 听了课程之后,有一点印象比较深刻,select模式是使用一个线程做监听,而bio每次来一个链接都要做线程切换,所以节省的时间在线程切换上,当然如果是c/c++实现,原理也是一样的。 想问一个一直困惑的问题,select内部如何实现的呢? 个人猜测:不考虑内核,应用层的区分,单纯从代码角度考虑,我猜测,当select开始工作时,有一个定时器,比如每10ms去检查一下网络缓冲区中是否有tcp的链接请求包,然后把这些包筛选出来,作为一个集合(即代码中的迭代器)填入java select类的一个集合成员中,然后唤醒select线程,做一个while遍历处理链接请求,这样一次线程调度就可以处理10ms内的所有链接。与bio比,节省的时间在线程上下文切换上。不知道这么理解对不对。 另外,也希望能出一个课程,按照上面这种理解底层的方式,讲讲select(因为我平常工作在linux机器,所以对select epoll比较感兴趣)如何处理read,write操作的。谢谢~
作者回复: 坦白说,内核epoll之类实现细节目前我的理解也有限
2018-05-319 - 萧萧作者对同步/异步, 阻塞/非阻塞的概念说明存在问题。 《操作系统(第9版)》中关于进程通信中有对这部分概念做过解释, 在进程间通信的维度, 同步和阻塞,异步和非阻塞是相同的概念。 沿着作者的概念解释简单推论一下就可以发现: 如果同步操作是需要等待调用返回才能进行下一步, 显然这个调用是阻塞的。 反之, 不需要等待调用返回的接口,必然需要提供事件, 回调等机制,这种调用显然是非阻塞的。
作者回复: 这东西并没有完全共识,概念定义要看上下文,很多情况下可以算是同等,但在网络IO编程中是区分的,本文的关注点就是这个
2018-08-0838 - lorancechen还有一个问题请教,select在单线程下处理监听任务是否会成为瓶颈?能否通过创建多个select实例,并发监听socket事件呢?
作者回复: Doug Lea曾经推荐过多个Selector,也就是多个reactor,如果你是这意思
2018-05-317 - 残月@诗雨杨老师,有个问题一直不太明白:BufferedInputStream和普通的InputStream直接read到一个缓冲数组这两种方式有什么区别?
作者回复: 我理解是bufferedIS是内部预读,所以两个buffer的意义不一样,前面是减少磁盘之类操作
2018-05-2925