结果
123456789
ThreadPoolExecutor-0_0单个任务返回:103------------------------------ThreadPoolExecutor-0_0ThreadPoolExecutor-0_1ThreadPoolExecutor-0_2多个任务返回:101多个任务返回:103多个任务返回:105
多进程引用模块
12345678
from multiprocessing import Processdef func(num):return numt = Process(target=func, args=(100,))t.start()t.join()
数据通信
1234
import multiprocessingq = multiprocessing.Queue()q.put(1)item = q.get()
锁
12345
from multiprocessing import Locklock = Lock()with lock:pass
池化技术
12345678
from concurrent.futures import ProcessPoolExecutorwith ProcessPoolExecutor() as executor:# 方法1results = executor.map(func, [1, 2, 3])# 方法2future = executor.submit(func, 1)result = future.result()
示例
12345678910111213141516171819202122232425
from concurrent.futures import ProcessPoolExecutorimport multiprocessingimport time# 定义一个准备作为进程任务的函数def action(num):print(multiprocessing.current_process().name)time.sleep(num)return num + 100if __name__ == "__main__":# 创建一个包含3条进程的进程池with ProcessPoolExecutor(max_workers=3) as pool:future1 = pool.submit(action, 3)future1.result()print(f"单个任务返回:{future1.result()}")print('------------------------------')# 使用线程执行map计算results = pool.map(action, [1, 3, 5])for r in results:print(f"多个任务返回:{r}")
结果123456789
SpawnProcess-1单个任务返回:103------------------------------SpawnProcess-2SpawnProcess-3SpawnProcess-1多个任务返回:101多个任务返回:103多个任务返回:105
多进程/多线程/协程对比异步 IO(asyncio)、多进程(multiprocessing)、多线程(multithreading)
IO 密集型应用CPU等待IO时间远大于CPU 自身运行时间,太浪费;
常见的 IO 密集型业务包括:浏览器交互、磁盘请求、网络爬虫、数据库请求等
Python 世界对于 IO 密集型场景的并发提升有 3 种方法:多进程、多线程、多协程;
理论上讲asyncio是性能最高的,原因如下:
- 进程、线程会有CPU上下文切换
- 进程、线程需要内核态和用户态的交互,性能开销大;而协程对内核透明的,只在用户态运行
- 进程、线程并不可以无限创建,最佳实践一般是 CPU*2;而协程并发能力强,并发上限理论上取决于操作系统IO多路复用(linux下是 epoll)可注册的文件描述符的极限
请求10此,并sleep 1s模拟业务查询
- 方法 1;顺序串行执行
- 方法 2:多进程
- 方法 3:多线程
- 方法 4:asyncio
- 方法 5:asyncio+uvloop
官方测试性能是 node.js的 2 倍,持平 golang 。
文章插图
顺序串行执行
12345678910111213141516171819
import timedef query(num):print(num)time.sleep(1)def main():for h in range(10):query(h)# main entranceif __name__ == '__main__':start_time = time.perf_counter()main()end_time = time.perf_counter()print(f"时间差:{end_time-start_time}")
多进程
123456789101112131415161718192021
from concurrent import futuresimport timedef query(num):print(num)time.sleep(1)def main():with futures.ProcessPoolExecutor() as executor:for future in executor.map(query, range(10)):pass# main entranceif __name__ == '__main__':start_time = time.perf_counter()main()end_time = time.perf_counter()print(f"时间差:{end_time-start_time}")
多线程
123456789101112131415161718192021
from concurrent import futuresimport timedef query(num):print(num)time.sleep(1)def main():with futures.ThreadPoolExecutor() as executor:for future in executor.map(query, range(10)):pass# main entranceif __name__ == '__main__':start_time = time.perf_counter()main()end_time = time.perf_counter()print(f"时间差:{end_time-start_time}")
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2022 python图形界面框架推荐
- 初识python正则表达式
- Python垃圾回收机制,人生苦短,只谈风月,谈什么回收?
- Python实现天气查询功能
- 用Python爬取六大平台的弹幕、评论,看这一篇就够了
- Python 中的自然语言处理入门
- 用python帮别人写了个文字识别程序
- 3个提升Python运行速度的方法,很实用
- 手把手教你编写Python抢购脚本
- Python生成遍历暴力破解密码,实战的效果差强人意了