JavaScript是单线程的,无法真正并行执行CPU密集型任务,但可通过事件循环和异步I/O实现高效并发;并发指任务交替推进与协作,而并行需多线程/多进程支持,如Web Workers或Node.js worker_threads。

并发(Concurrency)和并行(Parallelism)在 JavaScript 异步编程中常被混用,但它们描述的是不同层面的执行模型。JavaScript 本身是单线程的,这意味着它**无法真正并行执行 CPU 密集型任务**;但它通过事件循环、任务队列和异步 I/O 支持高效的并发处理。理解两者的本质区别,有助于写出更合理、可维护的异步代码。
并发:同一时间段内“看似”多个任务交替推进
并发强调的是任务的**组织方式与调度逻辑**——系统有能力管理多个任务的生命周期,让它们在时间上重叠、相互协作,哪怕实际执行是轮流切换的。
- JavaScript 中的
setTimeout、Promise.then、async/await都是构建并发行为的工具,它们把任务交由事件循环调度,在宏任务/微任务队列中排队执行 - 例如同时发起 5 个
fetch请求,它们会“并发”发出(几乎同时触发网络请求),但响应处理仍按顺序进入微任务队列(取决于响应到达时间) - 并发不保证快,但提升了资源利用率(比如等待 I/O 时去处理其他就绪任务)
并行:真正意义上多个任务在同一时刻物理执行
并行依赖于多核 CPU 或多进程/多线程环境,需要底层运行时支持真正的“同时执行”。JavaScript 主线程天然不具备这一能力。
- 浏览器中可通过
Web Workers创建独立线程,实现 CPU 密集型任务的并行计算(如图像处理、加密运算) - Node.js 可借助
worker_threads模块或child_process启动子进程,绕过单线程限制达成并行 - 注意:即使使用 Worker,主线程与 Worker 之间仍需通过消息传递通信,不存在共享内存意义上的直接协作
常见误区澄清
很多开发者误以为 Promise.all 是“并行执行”,其实它只是**并发发起异步操作**,真正的并行与否取决于底层实现:
立即学习“Java免费学习笔记(深入)”;
-
Promise.all([fetch(a), fetch(b)])是并发请求,网络层可能并行发包(由浏览器/操作系统决定),但 JS 层仍只做调度,不控制底层线程 - 若用
Promise.all执行纯计算函数(如fib(40)),这些函数会在主线程依次同步执行,完全无并发也无并行,反而造成阻塞 - 所谓“并行请求”其实是 I/O 层的特性,不是 JS 语言或运行时提供的并行能力
如何选择合适模型?
判断依据应基于任务类型和瓶颈所在:
- I/O 密集型(API 调用、文件读写、数据库查询)→ 优先用并发(
async/await+Promise.all等)即可高效利用等待时间 - CPU 密集型(大量数学运算、字符串处理、解码压缩)→ 必须剥离到 Worker 或子进程,否则阻塞事件循环,破坏并发效果
- 需要协调多个长期运行任务的状态 → 使用并发原语(如
AbortController、状态机、任务取消逻辑),而非强行模拟并行
JavaScript 的强大之处不在硬件并行,而在其轻量、灵活的并发抽象。掌握事件循环机制、区分 I/O 与 CPU 瓶颈、善用平台能力(Worker、Stream、Top-level await),才能真正驾驭异步编程的本质。











