异步IO Python语法-多进程、多线程、协程

相关概念

异步IO Python语法-多进程、多线程、协程

文章插图
 
并发和并行
  • 并发:指一个时间段内,在一个CPU(CPU核心)能运行的程序的数量 。
  • 并行:指在同一时刻,在多个CPU上运行多个程序,跟CPU(CPU核心)数量有关 。
因为
计算机CPU(CPU核心)在同一时刻只能运行一个程序 。
同步和异步
  • 同步是指代码调用的时候必须等待执行完成才能执行剩余的逻辑 。
  • 异步是指代码在调用的时候,不用等待操作完成,直接执行剩余逻辑 。
阻塞和非阻塞
  • 阻塞是指调用函数的时候当前线程被挂起 。
  • 非阻塞是指调用函数时当前线程不会被挂起,而是立即返回 。
CPU密集型和I/O密集型CPU密集型(CPU-bound):
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的运行
异步IO Python语法-多进程、多线程、协程

文章插图
 
Python的多线程是伪多线程,同时只能有一个线程运行 。
一个进程能够启动N个线程,数量受系统限制 。
一个线程能够启动N个协程,数量不受限制 。
怎么选择
对于其他语言来说,多线程是能同时利用多CPU(核)的,所以是适用CPU密集型计算的,但是Python由于GIL的限制,只能使用IO密集型计算 。
所以对于Python来说:
对于IO密集型来说能用多协程就用多协程,没有库支持才用多线程 。
对于CPU密集型就只能用多进程了 。

异步IO Python语法-多进程、多线程、协程

文章插图
 
协程(异步IO)简单示例 123456789101112131415import asyncioasync def test():await asyncio.sleep(3)return "123"async def main():result = await test()print(result)if __name__ == '__main__':asyncio.run(main())  
单次请求查看结果 12345678910111213141516171819import 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() 或者
123456789101112131415import 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()  
多次请求查看结果 123456789101112131415161718import 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()


推荐阅读