You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin测试协程与线程差异 启动百万线程未触发OOM问题咨询

测试未触发OOM的核心原因

你的代码和运行方式存在几个明显问题,根本没有复现对应测试场景:

  • 第一处代码错误:你没有按要求移除外层的runBlocking。runBlocking只会等待其协程作用域内的协程任务执行完成,你内部启动的是JVM原生平台线程,和runBlocking的协程上下文没有绑定关系。更关键的是,启动100万个线程的循环是单线程顺序执行的:创建一个平台线程本身需要微秒到毫秒级的开销,按每秒创建1万个线程的速度算,跑完100万次循环需要近2分钟,而你线程内写的sleep(5000L)只会让线程存活5秒,也就是说循环还没跑完1/10,最早启动的线程就已经执行完退出了,同一时间存活的线程数远达不到100万的量级,自然吃不到触发OOM的内存量。
  • 第二处环境限制:普通消费级操作系统默认对单进程可创建的平台线程数有严格限制,Linux/macOS/Windows的默认阈值大多在几千到几万之间,根本不可能创建出100万个同时存活的平台线程。当循环创建线程数达到系统阈值时,会抛出OutOfMemoryError: unable to create native thread错误,这个错误会直接中断跑循环的主线程,后续的线程创建逻辑直接终止,而已经创建的几千个线程会在sleep结束后打印.再退出。大量的打印输出很容易把前面的错误栈冲掉,再加上IDE控制台默认有输出行数限制,错误信息会被挤出可视区域,你肉眼很容易忽略掉已经抛出的错误。
  • 第三点认知偏差:相关文档描述的核心是平台线程的内存开销远高于协程——单个JVM平台线程默认要占用1MB左右的栈内存,光是100万个线程的栈内存就需要近1TB,普通消费级硬件根本不可能支撑,而单个协程的内存开销只有几十字节,100万个协程只需要几十MB内存就能跑。你没看到OOM不代表线程和协程开销相当,只是你根本没造出100万个线程同时存活的场景而已。
正确的验证方式

如果要直观看到两者的差异,可以按下面的方式调整:

  1. 去掉外层的runBlocking包装,main方法直接执行线程/协程创建逻辑
  2. 协程版本直接启动100万个协程执行delay,你会看到程序只占几十MB内存,几秒后就开始稳定打印.,运行全程没有明显卡顿
  3. 线程版本不需要硬凑100万的量级,可以先从1万个线程开始测试,逐步往上加,你会发现加到几万线程的时候程序内存就会涨到几个G,系统开始明显卡顿,很快就会抛出无法创建线程的错误,和协程版本的开销差距非常明显

注意:如果你使用的是JDK 21+版本,要确认调用的thread方法创建的是平台线程而非虚拟线程,虚拟线程的开销虽然比传统平台线程低很多,但和协程的调度模型、适用场景仍有差异,不要混为一谈。

内容的提问来源于stack exchange,提问作者user9628944

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:54:17