Java NIO 到底是异步还是同步,阻塞还是非阻塞?

2018-07-29 14:04:52 +08:00
 wanderlustLee

今天刚刚学习 NIO,网上看了好多资料,有说是异步阻塞的,还有说是同步非阻塞的。好像是因为关注点不同,select 线程是阻塞的?对多个流处理又是非阻塞的?有大神来解释一下吗。。。

10363 次点击
所在节点    Java
24 条回复
woncode
2018-07-29 14:21:48 +08:00
只记得是非阻塞

从百度百科看异步的定义
『异步的另外一种含义是计算机多线程的异步处理。与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。』

这么说非阻塞那就是异步了
wanderlustLee
2018-07-29 14:36:57 +08:00
@woncode 但有人说异步是对于操作系统通知线程的,而 NIO 还是启了一个线程去监听事件的。所以说是同步。。。。有点懵
xhystc
2018-07-29 14:50:17 +08:00
nio 的多路复用是属于同步非阻塞
Srar
2018-07-29 14:53:56 +08:00
底层已经改成 epoll Selector 底层初始化时候回申请一个 128 长度的事件数组 当 epoll 通知事件时候 jvm native 层会直接往这事件数组里插事件 你要做的事就是把事件拿出来。。。
alamaya
2018-07-29 14:54:52 +08:00
nio 底层就是 epoll 当然是同步非阻塞的
hecz
2018-07-29 15:01:07 +08:00
@wanderlustLee 同步和异步的区别就是同步会在整个 io 操作中导致进程阻塞,而异步不会。异步非阻塞 IO 只属于这种情况,就是我发送一个 io 请求,操作系统帮你做好各种事,包括获取 io 流,以及将 io 流从内核拷贝到用户空间,你只需要收到完成的通知即可。而 NIO 是多路复用 IO,他虽然在获取内核的数据时不会阻塞,但是它却会在将内核数据拷贝到用户空间的时候线程阻塞。所以 NIO 是同步非阻塞。
lhx2008
2018-07-29 15:02:01 +08:00
按照某大神书上的理论,是叫做同步非阻塞,不过我觉得他开心就好。

按照我的理解,默认实现是,分配 channel 可以线程复用,即每一个线程可以同时绑定多个 channel (传统的只能绑定一个),那么这样这个线程的空闲时间会比较少,效率会比较高。

然后,每个线程中默认是阻塞或者叫同步的,就是和传统的没差。该花的时间还是要花。

再之后,我们可以在 NIO 的基础上改成异步的,就是一个线程不光可以处理 channel 上面的用户事件,还可以执行我们自己定义的事件。在处理 channel 事件时,不阻塞马上返回,并且把相关的操作打包成一个事件,并且告诉这个事件干完这件事情(这个可能不是自己干而是别人干),还要干什么事情。然后这个事件也在这个线程的排队队列中处理。这样可以进一步压缩这个线程的空闲时间。这就是 NETTY 的实现。只需要少量的线程就可以得到比较高的效率。

当然,你可能觉得上面的这样做效率并没有什么提高,那么,我们还可以再维护一个稍大的池子专门处理阻塞时间比较久的事件的线程池。这是 Vertx 里面对 netty 的改进。
nl101531
2018-07-29 15:04:28 +08:00
同步非阻塞,同步体现在 selector 仍然要去轮循判断 channel 是否准备好,非阻塞体现在这个过程中处理线程不会一直在等待,可以去做其他的事情。
pkaq
2018-07-29 15:07:27 +08:00
Blocking IO/ Non-Blocking IO / asynchronous I/O
coldear
2018-07-29 15:08:03 +08:00
是同步非阻塞的( non-blocking IO)。
从 channel 读的时候,不确定能读出多少,会立刻返回当前能读到的东西。你的代码得处理这些情况,可以干别的事情之类。
selector 是说你可以注册多个 channel,你的代码可以不停的去调用 select(), 当有 IO 可以读取的时候,你可以处理,没有的话你可以在代码里干别的事。
NIO 总之是为了代码不要被 IO 阻塞,但代码写起来相对麻烦一点。
nl101531
2018-07-29 15:08:42 +08:00
@nl101531 补充下,同步异步关注点是你问内核数据有没有准备好,还是内核主动通知你数据有没有准备好。阻塞非阻塞关注点时你的处理线程在数据没有准备好的时候是一直在等待状态还是可以去做其他的事情。
twogoods
2018-07-29 15:18:42 +08:00
select 确实是阻塞的,但没有一个请求线程会是阻塞的,同步非阻塞
WordTian
2018-07-29 15:31:26 +08:00
看看 netty 权威指南前两章吧,那块有几个流程图把这个区别解释的很清楚
zmxnv123
2018-07-29 16:05:29 +08:00
同步非阻塞,异步的请左转看 AIO,好像 JDK1.7 引入的。
qk3z
2018-07-29 18:03:48 +08:00
建议看看《 netty 权威指南》,讲的还是很明白的
wanderlustLee
2018-07-30 08:52:08 +08:00
@xhystc
@Srar
@alamaya
@hecz
@lhx2008
@nl101531
@pkaq
@coldear
@nl101531
@twogoods
@WordTian
@zmxnv123
@qk3z
恩恩,明白了。肥肠感谢!
owenliang
2018-07-30 08:55:08 +08:00
走 select 是异步,否则是同步。
cyspy
2018-07-30 09:22:19 +08:00
很多人是把 BIO NIO AIO 并列
wanderlustLee
2018-07-30 09:35:50 +08:00
@nl101531 老哥说的很形象,理解了
wanderlustLee
2018-07-30 09:38:27 +08:00
@lhx2008 那么在 NIO 中的绑定多个 channel 的线程是不可以去做其他的事情吗,只能用来处理这些 channel 吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/475074

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX