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

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.

如果有不同意见的小伙伴可以留言,我觉得这个可以作为一个面试题。
17143 次点击
所在节点    Java
154 条回复
byte10
2022-04-19 10:07:19 +08:00
@jeesk 少年,你多听前辈的。我来给你一一解答把,第一点:你用 BIO 和 NIO 都是 200 个线程 ,首先你条件是错了。。NIO 只要 4 个线程即可。另外要验证 BIO 上下文切换厉害,这个是需要在 IO 时间很短的情况下才会出现,且 200 个线程不算啥,你得开 1000 个线程才能看出有差距。

所以你要验证线程上下文切换的损耗,我给你一个测试的方案。写一个 main 方法,一个用 4 个线程,一个用 200 个线程,处理的任务是:判断 100000007 是否为一个质数(一个线程计算一个数,总共相同计算 500 次),一个数 for 循环一亿次去判断,最终得到的是 4 个线程比 200 个线程快,原因就是线程切换会有开销,至于你看起来差不多,那是因为现在的 cpu 单核很快。你可以换成树莓派,或者手机 linux deploy ,或者几年前的双核 I3 去验证。你要多学习,多思考。不然以后会误导后辈的,我们公司都很多这样的小白,没有完整的验证方案,因为不懂这基础知识,所以没法设计验证的方案。

第二个问题:一般 BIO - tomcat ,如果有 2000 个用户在线,那么就需要 2000 个线程,除非用伪 BIO 。

第三个问题:你的思路很混乱,我暂时无法回答,也不知道从哪里回答你。

对于 NIO 你先看我的视频,如果能看懂,你就算是毕业了,如果还没看懂,那么是我的讲的还不行。里面有大量的 test case 去验证 tomcat 线程数的数量该设置多少,https://www.bilibili.com/video/BV1FS4y1o7QB ,主页我还有一个视频讲多线程的,应该对你也有帮助。。

@jeesk 关于 tomcat NIO 和 BIO 为何默认 200 个线程。这个从你目前的知识,无法解答。答案在视频里,如果你看懂了,自然明白。里面有大量的数据可以验证,tomcat 有 NIO 但是大多数人 还不会使用。tomcat NIO 的 支持 servlet 用异步编程的模式,只需要设置 tomcat 线程数等于 cpu 核心数 即可。里面有大量的例子给你证明的,希望你能明白。

@hidemyself 你可以看看我的视频,应该能回到你的问题 https://www.bilibili.com/video/BV1FS4y1o7QB
Edsie
2022-04-19 10:09:14 +08:00
没有任何时候比现在更容易从互联网上获取信息
大爆炸似的信息增长,导致了两个结果:
1. 你能在互联网上找的到非常优质的内容
2. 从量上来看,垃圾信息也在恐怖的增长,至于好的信息和垃圾信息的比例就不得而知了

所以这对人们提出了更高的要求,现状是:有能力的人总能找出他们需要的信息。
lisongeee
2022-04-19 10:11:06 +08:00
"我个人觉得差不了多少。 所以这个说法是错的。"

不要凭感觉啊,拿 cpu 占用率和程序使用内存数据说话啊
jeesk
2022-04-19 10:19:14 +08:00
@nothingistrue 你确定吗? tomcat8.5 才默认为 nio , 你这数据哪儿来的?
byte10
2022-04-19 10:19:45 +08:00
@Jekins 可以看看我的视频。B 站:小巫老师,视频:NIO 二 实战演练 ,里面就一个几个案例,讲到为何要用 NIO 。另外一个 视频:NIO 的绝对优势 这个视频非常的强,可以打开 NIO 的思路。里面有很多测试代码,可以帮组你理解 NIO 为何几个线程就可以吊打 BIO 几千个线程。

@nothingistrue 正确,200 个线程难以看出差距,不过在低端 cpu 可以看出和 4 个线程的差距,高端 cpu 起码 2000 个线程和 10 个线程对比才能看出来,另外要测试的话 需要用 cpu 密集型任务去验证,很多小白会用 IO 任务去验证。。我头大。

@hidemyself 你可以看看我的视频,B 站:小巫老师,NIO 二 实战演练,讲述了为何需要 NIO 的场景,里面有很多测试的代码,看完你应该就能明白,NIO 有绝对的性能优势。 等 java 的协程出来,BIO 就基本不会在用了。
jeesk
2022-04-19 10:20:40 +08:00
@byte10 你是来推广视频的吧 哈哈
chnhyg
2022-04-19 10:23:36 +08:00
尽量接近信息源头,信息源头的错误率和失真率是最少的,二手、三手信息是别人嚼碎了再吐出来的,有一定的错误和失真。
byte10
2022-04-19 10:27:05 +08:00
@jeesk 哈哈,先看完,如果有问题可以留言或者 加绿色。我已经给你答案了,还有很多测试的代码,可以验证你的疑虑。为何 tomcat NIO 等于没用?因为下游的业务代码全是阻塞 IO 代码,所以你才会看到 tomcat NIO 依然需要默认 200 个线程。而 webflux 默认就是 cpu 核心数的线程,因为它是响应式编程。除了 webflux ,还有一个 vert.x 使用异步编程,也可以做到少量线程。当然你的业务如果是阻塞 IO 的操作,比如 mysql 读写等,还是需要创建的线程池去处理。

作为一个后辈,我是需要你做出指引,给大家做出指引,科普知识非常的困难,我尽力而为。当然你说的推广算是附带的吧。
Leviathann
2022-04-19 10:33:17 +08:00
为什么用 nio 还要开那么多线程,nio 的目的不就是用少量线程管理大量 io

而且为什么一直要说 tomcat 怎么怎么样,tomcat 是什么在单机高并发场景下很有代表性的东西吗?现在用 tomcat 的场景堆并发不都是堆机器,单机并发烂的很,不然还要 go 干嘛
jeesk
2022-04-19 10:45:21 +08:00
@chnhyg 给你赞。 我就是这样学的。 看别人写的东西 会出现很大的问题 。
zmal
2022-04-19 11:00:32 +08:00
哈哈哈哈哈哈,op 再过两年回头看看自己的帖子(手动狗头。
az467
2022-04-19 11:00:40 +08:00
没错,一切都是根据需求而言。

如果我完全不在乎某些指标,比如 tps 、rt 、throughput ,只看内存占用或者其他什么的。
那不论是 Blocking IO 还是 Non-blocking IO ,肯定都比不上 No IO 。
我只要一个线程都不开,一行代码也没有,内存占用 0 ,上下文切换代价也是 0 ,不要说什么 M 级的内存消耗( https://en.wikipedia.org/wiki/Page_fault ),G 级别又能怎样。

如果要解决 C10K/C10M 问题,那就不得不给 BIO 模型的服务软件配一个 IBM 小型机。
nekoneko
2022-04-19 11:06:32 +08:00
在少量连接的情况下 bio 的性能是优于 nio 的
但是在大量连接的情况下, 比如说十万百万, 这种情况下 bio 就要建立十万百万的线程, 这个用 bio 处理基本离死不远了
但 nio 就可以处理这种场景.
ecric
2022-04-19 11:15:26 +08:00
别他妈卷了
zmal
2022-04-19 11:25:07 +08:00
有没有一种可能,你的测试场景、测试手段都有问题?(狗头
seagull7558
2022-04-19 11:32:12 +08:00
知秋没深入接触过 不过看过一些翻译的课程,我觉得,emmmmm 哈可以吧 不晓得他是和其他人有什么冲突吗?
xuanbg
2022-04-19 11:46:15 +08:00
BIO 还是 NIO ,只要看阻塞的是什么就知道怎么选了啊,同时也就知道能开几个线程去处理了。
yigecaiji
2022-04-19 12:20:55 +08:00
初学者的理解:
bio 下,n 个 socket 连接需要一个线程来处理请求,同时每个 socket 需要 2 个线程来处理读写。
nio 同步非阻塞下,n 个 socket 的请求、读、写操作可以由一个线程来完成,但没有这些操作的时候,线程还在运行,浪费 cpu
nio 多路复用下,n 个 socket 的请求、读、写操作可以由一个线程来完成,如果没有这些操作,线程就会阻塞。
我不知道 tomcat 的机制,不过相同 socket 的情况下,nio 开的线程应该是比 bio 要少的。
jeesk
2022-04-19 12:35:46 +08:00
@yigecaiji 自己看源码
jeesk
2022-04-19 12:37:20 +08:00
@seagull7558 我从来没说过他的水平,我也不清楚他是不是大神。 我更加看中 人品

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

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

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

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

© 2021 V2EX