当前位置: 首页 > news >正文

WHAT - 协程及 JavaScript 具体代码示例

文章目录

  • 和线程的区别
  • 协程的特点
  • 协程+事件循环的调度方式
    • 关键点
    • 举个例子(直观理解)
    • 结论:适合 I/O 密集型任务,不适合 CPU 密集型任务
  • 常见语言中的协程基本使用
    • Python 和 Go
    • JavaScript 更具体的代码示例
      • 普通同步写法(阻塞 I/O,串行执行)
      • 协程/异步写法(高并发 I/O,几乎同时发出请求)
  • 简单总结

协程(Coroutine)是一种比线程更轻量级的并发编程方式。它的核心思想是:在单个线程中,通过挂起与恢复来实现多任务的协作执行。


和线程的区别

  • 线程:由操作系统调度,开销大,切换时需要保存上下文,可能涉及内核态和用户态切换。
  • 协程:由用户代码控制切换,不需要操作系统参与,切换开销小,通常只是在用户态保存/恢复栈和寄存器。

协程的特点

  1. 轻量:一个线程可以运行成千上万个协程。
  2. 非抢占式:协程的切换是显式的(例如 await / yield),不会像线程那样随时被抢占。
  3. 顺序写法、异步执行:代码看起来像同步,但实际上在等待 I/O 时切换到其他任务,提高效率。
  4. 常用于高并发、I/O 密集型:比如网络请求、数据库操作、文件读写。

协程+事件循环的调度方式

在前面介绍中,直觉上会以为协程像单线程一样“排队执行”,怎么还能支持高并发呢?核心原因在于 协程+事件循环(event loop) 的调度方式

关键点

  1. 顺序是单个线程内的顺序
    协程本质上还是运行在一个线程里,的确不会同时并行执行。
    但是:当一个协程遇到 I/O 操作(比如网络请求、文件读写、数据库查询) 时,它不会傻等,而是“让出控制权”,切到下一个协程继续执行。

  2. 节省了等待的时间
    在传统线程里,一个阻塞的 I/O 操作可能要等几百毫秒甚至几秒,这段时间线程就闲着,浪费资源。
    协程则在这段时间里切去运行其他任务,把 CPU 充分利用起来。

  3. 数量极多
    因为协程是用户态的轻量调度,一个协程只占用 KB 级别的内存,成千上万个协程同时存在几乎没什么问题。
    相比之下,线程每个可能占 MB 级别内存,操作系统还要做上下文切换,几千个线程就会崩溃。

举个例子(直观理解)

  • 线程模型
    你有 10 个服务员(线程),每个人点单后要傻等厨房出菜(阻塞),需要很多服务员才能服务 100 桌客人。

  • 协程模型
    你只雇 1 个服务员(单线程),但他点完单就去服务下一桌(切换协程),厨房做好菜再通知他回来送菜。
    这样 1 个服务员就能高效服务成百上千桌,因为大部分时间都在等菜,而不是一直闲着。

结论:适合 I/O 密集型任务,不适合 CPU 密集型任务

  • 协程 不是真正的并行,它们是 高效的并发
  • 高并发来自于:在 I/O 等待时不浪费时间,能调度成千上万个协程轮流执行。
  • 如果是 CPU 密集型任务(比如压缩视频、训练模型),协程就没优势,还是要靠多线程/多进程。

常见语言中的协程基本使用

Python 和 Go

  • Python

    import asyncioasync def fetch_data():print("开始获取数据...")await asyncio.sleep(2)  # 模拟IO操作print("获取完成")return {"data": 123}async def main():result = await fetch_data()print(result)asyncio.run(main())
    
  • Go(通过 goroutine 实现,虽然严格说是“协程模型”而不是协程本身)

    package mainimport ("fmt""time"
    )func worker() {fmt.Println("开始工作...")time.Sleep(2 * time.Second)fmt.Println("完成工作")
    }func main() {go worker()  // 启动协程time.Sleep(3 * time.Second)
    }
    

JavaScript 更具体的代码示例

普通同步写法(阻塞 I/O,串行执行)

function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));
}async function fetchData(id) {console.log(`开始获取数据 ${id}`);await sleep(2000); // 模拟网络 I/Oconsole.log(`完成获取数据 ${id}`);return { id, data: 123 };
}async function main() {console.time("total");await fetchData(1);await fetchData(2);await fetchData(3);console.timeEnd("total");
}main();

👉 执行结果:

开始获取数据 1
完成获取数据 1
开始获取数据 2
完成获取数据 2
开始获取数据 3
完成获取数据 3
total: ~6000ms

每次都要等上一个任务完成,总耗时 ≈ 2000ms × 3


协程/异步写法(高并发 I/O,几乎同时发出请求)

function sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));
}async function fetchData(id) {console.log(`开始获取数据 ${id}`);await sleep(2000); // 模拟网络 I/Oconsole.log(`完成获取数据 ${id}`);return { id, data: 123 };
}async function main() {console.time("total");const tasks = [fetchData(1), fetchData(2), fetchData(3)];const results = await Promise.all(tasks);console.log(results);console.timeEnd("total");
}main();

👉 执行结果:

开始获取数据 1
开始获取数据 2
开始获取数据 3
完成获取数据 1
完成获取数据 2
完成获取数据 3
total: ~2000ms
  • 并没有多线程,还是在一个线程里。
  • 但是 3 个请求同时挂起等待 I/O,等待时 CPU 空出来去跑其他协程。
  • 总耗时 ≈ 单个请求的耗时(2000ms),而不是叠加。

这就体现了 高并发 I/O 密集型 的优势:协程(async/await)+ 事件循环,使得单线程可以同时处理成百上千个 I/O 请求,而不用为每个请求都开一个线程。


简单总结

  • 协程是一种 用户态的轻量线程
  • 主要解决 高并发、I/O密集 的场景问题(结合事件循环进行调度)。
  • 用“看似同步,实则异步”的写法提升代码可读性。
http://www.dtcms.com/a/365645.html

相关文章:

  • PgManage:一款免费开源、跨平台的数据库管理工具
  • Packet Radio Network,PRNET
  • 从发现到恢复,看瑞数信息如何构建“抗毁重构”实战路径
  • VR节约用水模拟体验系统:沉浸式体验如何改变我们的用水习惯
  • 全员0门槛数据分析:纷享销客BI Agent,让数据价值直抵业务
  • 实现信号的小波分解和重构
  • 自动化仓库托盘搬运减少错误和损坏的方法有哪些?实操案例解读
  • 12、Docker基本概念 容器与镜像与安装
  • MyBatis xml配置文件
  • 借助Aspose.ZIP SDK,在 C# 中压缩和提取 LZIP 文件
  • ubuntu的2T新硬盘分区、格式化并挂载
  • Linux学习:生产者消费者模型
  • 明远智睿 3568 核心板:四核 Cortex - A55 架构驱动的性能新标杆
  • C++中cdecl、stdcall、fastcall、thiscall异同——10分钟弄清
  • linux0.12 head.s代码解析
  • Alpha World赞助Hello Blockchain Thailand,AWT成为全球共识焦点
  • 袋鼠云产品功能更新报告14期|实时开发,效率再升级!
  • 【IQA技术专题】NIQE代码讲解
  • VMWare上搭建分布式Hadoop集群
  • STM32F103按钮实验
  • 大语言模型领域最新进展
  • 笔记:卷积神经网络(CNN)
  • rust学习之开发环境
  • 从 0 到 1 吃透 Nacos:服务发现与配置中心的终极实践指南
  • 阅兵时刻,耐达讯自动化RS485 转 Profinet 网关助力矿山冶金连接迈向辉煌
  • BurpSuite_Pro_V2024.6使用教程-Burp Suite代理设置详解
  • 张琦《认知破局》读书笔记
  • 内存保护单元MPU
  • 用资产驱动方法构建汽车网络安全档案
  • 中科米堆CASAIM自动化三维测量设备测量汽车零部件尺寸质量控制