相关概念
文章插图
并发和并行
- 并发:指一个时间段内,在一个CPU(CPU核心)能运行的程序的数量 。
- 并行:指在同一时刻,在多个CPU上运行多个程序,跟CPU(CPU核心)数量有关 。
计算机CPU(CPU核心)在同一时刻只能运行一个程序 。同步和异步
- 同步是指代码调用的时候必须等待执行完成才能执行剩余的逻辑 。
- 异步是指代码在调用的时候,不用等待操作完成,直接执行剩余逻辑 。
- 阻塞是指调用函数的时候当前线程被挂起 。
- 非阻塞是指调用函数时当前线程不会被挂起,而是立即返回 。
CPU密集型又叫做计算密集型,指I/O在很短时间就能完成,CPU需要大量的计算和处理,特点是CPU占用高 。
例如:压缩解压缩、加密解密、正则表达式搜索 。
IO密集型(I/O-bound):
IO密集型是指系统运行时大部分时间时CPU在等待IO操作(硬盘/内存)的读写操作,特点是CPU占用较低 。
例如:文件读写、网络爬虫、数据库读写 。
多进程、多线程、多协程的对比
优点
缺点
适用
多进程
Process(multiprocessing)
可以利用CPU多核并行运算
占用资源最多
可启动数目比线程少
CPU密集型计算
多线程
Thread(threading)
相比进程更轻量占用资源少
相比进程,多线程只能并发执行,不能利用多CPU(GIL)
相比协程启动数目有限制,占用内存资源有线程切换开销
IO密集型计算、同时运行的任务要求不多
多协程
Coroutine(asyncio)
内存开销最少,启动协程数量最多
支持库的限制
代码实现复杂
IO密集型计算、同时运行的较多任务
GIL全称Global Interpreter Lock
下图为GIL的运行
文章插图
Python的多线程是伪多线程,同时只能有一个线程运行 。
一个进程能够启动N个线程,数量受系统限制 。
一个线程能够启动N个协程,数量不受限制 。
怎么选择
对于其他语言来说,多线程是能同时利用多CPU(核)的,所以是适用CPU密集型计算的,但是Python由于GIL的限制,只能使用IO密集型计算 。
所以对于Python来说:
对于IO密集型来说能用多协程就用多协程,没有库支持才用多线程 。
对于CPU密集型就只能用多进程了 。
文章插图
协程(异步IO)简单示例
123456789101112131415
import asyncioasync def test():await asyncio.sleep(3)return "123"async def main():result = await test()print(result)if __name__ == '__main__':asyncio.run(main())
单次请求查看结果
12345678910111213141516171819
import threadingimport asyncioasync def myfun(index):print(f'[{index}]({threading.currentThread().name})')await asyncio.sleep(1)return indexdef getfuture(future):print(f"结果为:{future.result()}")if __name__ == "__main__":loop = asyncio.get_event_loop()future = asyncio.ensure_future(myfun(1))future.add_done_callback(getfuture)loop.run_until_complete(future)loop.close()
或者123456789101112131415
import threadingimport asyncioasync def myfun(index):print(f'[{index}]({threading.currentThread().name})')await asyncio.sleep(1)return indexif __name__ == "__main__":loop = asyncio.get_event_loop()future = asyncio.ensure_future(myfun(1))loop.run_until_complete(future)print(f"结果为:{future.result()}")loop.close()
多次请求查看结果
123456789101112131415161718
import threadingimport asyncioasync def myfun(index):print(f'线程({threading.currentThread().name}) 传入参数({index})')await asyncio.sleep(1)return indexloop = asyncio.get_event_loop()future_list = []for item in range(3):future = asyncio.ensure_future(myfun(item))future_list.Append(future)loop.run_until_complete(asyncio.wait(future_list))for future in future_list:print(f"结果为:{future.result()}")loop.close()
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2022 python图形界面框架推荐
- 初识python正则表达式
- Python垃圾回收机制,人生苦短,只谈风月,谈什么回收?
- Python实现天气查询功能
- 用Python爬取六大平台的弹幕、评论,看这一篇就够了
- Python 中的自然语言处理入门
- 用python帮别人写了个文字识别程序
- 3个提升Python运行速度的方法,很实用
- 手把手教你编写Python抢购脚本
- Python生成遍历暴力破解密码,实战的效果差强人意了