从业时间越久,发现互联网很多知识都是错的, 对小白误导有多深?

2022-04-18 22:04:26 +08:00
 jeesk
说说我自己的看法, 无论是 csdn 还是知乎, 在我最开始从业 java 的时候,觉得他们说得没有毛病? 从业几年后,发现很多都是在鬼扯。 就拿 BIO 和 NIO 谁性能好, 知乎上面竞争激烈,下面我粘贴一个知乎的回答。

回答 1:

首先要明确一点:nio 的适用于 io 高并发场景线程开销包括:内存开销(创建一个线程需要为其分配和维护一个 tcb 线程控制块保存上下文,一个线程私有的栈)、线程上下文切换的时间开销(保存上下文,加载下一个线程的上下文),在高并发环境下多出来的这一点点开销积累起来是非常可观的。若使用 bio ,高并发必然引起激烈 contention ,导致大量的上下文切换,若采用一个 io 一个线程模型,一个线程 M 级的空间消耗,内存消耗不起。而 netty 采用 nio 加 selector 加线程池基本上解决了上述问题:一是线程池限制了内存消耗,二是采用 selector 使得只有处于活动状态的 io 才会去占用线程,不会使线程白白因为 io 而阻塞,提高了线程利用率。

说说他们的谬论:
1. 使用 BIO 上下文切换厉害, 如果是相同 4 核 cpu , 无论我是用 bio 还是 nio ,都用 200 个线程, 这个时候对 cpu 的竞争到底有多剧烈? 我个人觉得差不了多少。 所以这个说法是错的。

2. 若采用一个 io 一个线程模型,一个线程 M 级的空间消耗。 这个就更扯淡了。 即使是 tomcat 在 8.5 以前也是 BIO 200 个线程, 都没有用到 1w 个线程? 为什么非要扯开大量线程呢? 并且 tomcat 在 8.5 以后才默认 nio.

3. 一是线程池限制了内存消耗,二是采用 selector 使得只有处于活动状态的 io 才会去占用线程. 那我 tomcat 用 BIO 没有内存限制? 没有内存限制岂不是早就宕机了? 再说说 selector 的问题, 我 NIO 在 readSelector 开 10 个线程去调用 select, 不都是阻塞的吗? 怎么会说在活动状态才占用线程?

然后你会发现这些错误的回答有很多,下面还有大量的小白点赞,觉得说得很对。 但是一经脑子思考就发现, 这绝对是坑 B.

如果有不同意见的小伙伴可以留言,我觉得这个可以作为一个面试题。
17803 次点击
所在节点    Java
154 条回复
rahuahua
2022-04-20 09:28:44 +08:00
@jeesk CPU 密集型场景来测试 IO 模型的优略性,这是何苦呢
rahuahua
2022-04-20 09:32:58 +08:00
楼主可能也没经历过所谓的高并发,大牛搞出 NIO ,各种协程模型并不是闲的蛋疼,是真的因为需要,早些年还在讨论 C10K , 现在都在讨论 C1000K 是技术在进步。 不要觉得别人都是小白,这种心态不好
nothingistrue
2022-04-20 09:43:58 +08:00
发现楼上有些人是 “nio 优于 bio”,或者 “nio 要替代 bio” 的想法,这是不正确的。NIO 异步非阻塞,BIO 同步阻塞,这俩是应对不同场景的,不是不考虑场景就无脑用一个。如果是客户端应用读取一个文件准备编辑的场景,用 NIO 就是个沙雕(这里 UI 那里可以将读取文件的过程作为子过程异步调用,但读取文件这个过程,单线程阻塞是最优解)。

还有异步同步也是要分场景的,并且异步本身,也是分为全异步的 callback 模式跟异步同步结合的 async/await 模式。无脑异步,或者无脑 callback ,也是沙雕行为。

楼主是上面看法的反方,是错的,但不代表上面看法的正方就是对的。楼主的标题说的是很正确的,互联网上的很多知识都会带入非黑即白的世界观,这才是最大的误导。
SunFarrell
2022-04-20 09:45:57 +08:00
所以我们都看开发经验,技术类的文章都知道是花瓶,毕竟国内技术人员写技术文章表达能力不够严谨
bugFactory
2022-04-20 09:50:42 +08:00
@MoYi123 不用
bugFactory
2022-04-20 09:51:05 +08:00
@Jekins 你的问题加机器就可以解决
yazinnnn
2022-04-20 10:13:02 +08:00
楼主可以把测试的代码或者项目贴出来吗?想看看怎么写的
akira
2022-04-20 11:17:33 +08:00
每个人的认知都是不一样的,发出来的内容自然有可能会有偏差。 相比较之下,教科书的基础内容, 大牛的文章 出问题的概率就小很多,可信度较高,最多就是可能有过时。

总而言之,言而总之,看到一个东西,要自己思考
lmshl
2022-04-20 11:35:02 +08:00
@nothingistrue nio 确实完全优于 bio ,完全替代这毋庸置疑。2022 年的今天谁在 UI 线程读取文件?十年前都不这么做了好吧。
如果你真的基础扎实的话,你应该知道 memory hierarchy 中 CPU >> Memory >>> Disk ,即使是计算密集型应用,异步流式文件加载也可以尽可能的让计算过程提前开始,最简单的例子就是“读取 CSV 文件,统计数据”,省下来的 CPU 时间可以留给计算过程,让总计算时间缩的更短。
jeesk
2022-04-20 12:00:17 +08:00
@yazinnnn 代码是去年还是前年测试的, 那时候从运费同事借的测试机玩, 代码早就没了。
jeesk
2022-04-20 12:03:34 +08:00
@defage 你这样扛, 我是默认忽略的。 有几家公司,有多少服务比例直接上 32g ?
jeesk
2022-04-20 12:07:06 +08:00
@nothingistrue nio 并不是异步的。只是非阻塞而已。 真正的异步是 aio 。
jeesk
2022-04-20 12:10:26 +08:00
@yazinnnn https://www.jianshu.com/p/77e8b64ab710 测试的数据在这里, 不过没有内存的图而已。
jeesk
2022-04-20 12:12:28 +08:00
@rahuahua 我说我们生产是有一部分是密集应用。 我什么时候说过用 cpu 密集应用测试过? 又来倒打一把?
jeesk
2022-04-20 12:17:36 +08:00
@lmshl 你说得不对, 阻塞会线程让出 cpu 的。ui 线程不可能做耗时的操作的,这样 ui 线程会卡死。 异步处理就行了。 用这个例子证明 nio 和 bio 不太好。
lmshl
2022-04-20 12:21:29 +08:00
@jeesk “ui 线程不可能做耗时的操作的,这样 ui 线程会卡死。” 我说的和你说的不是一回事吗?
JavaScript 这么多年不就是这么处理的么?
而且 NIO 本身就是异步了
jeesk
2022-04-20 12:38:41 +08:00
@lmshl 浏览器不是单个线程,交互和渲染是分开的。 我说的 ui 可以用安卓线程来举例的。
liuhan907
2022-04-20 12:39:08 +08:00
@lmshl NIO 是同步非阻塞,并不是异步。
lmshl
2022-04-20 12:56:44 +08:00
@jeesk 但浏览器的 JS 是单线程的,交互是不分开的。Android/Winform/WPF 你也可以用 kotlin flow API ,和 C# async/await ,并没有什么不同。过去开新线程发信号,走 delegate ,今天纯异步 fiber
jeesk
2022-04-20 13:16:44 +08:00
@lmshl 单啥? 如果是单线程还能异步请求?

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

https://ex.noerr.eu.org/t/847761

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

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

© 2021 V2EX