线程,进程,协程
一、进程
多进程:
是CPU对程序的一次执行过程、一次执行任务。各个进程有自己的内存空间、数据栈等。操作系统分配内存的基本单位(打开、执行、保存…)
参考:
import os from multiprocessing import Process def func_one(): print("这是第一个子进程") print("son_one:%s father:%s" % (os.getpid(), os.getppid())) for i in range(1000): print("第一个子进程", i) def func_two(): print("这是第二个子进程") print("son_two:%s father:%s" % (os.getpid(), os.getppid())) for i in range(1000): print("这是第二个子进程", i) if __name__ == '__main__': p_one = Process(target=func_one) P_two = Process(target=func_two) #多个进程可以同用一个函数 # P_two = Process(target=func_two,args=("函数一",)) p_one.start() #p_one.join() # 主线程要等待func_one终止,才继续往下走 P_two.start() print("son:%s father:%s" % (os.getpid(), os.getppid())) # father是pycharm
进程池:
import time from concurrent.futures import ProcessPoolExecutor def fun(name): for i in range(1000): print(name,i) if __name__ == '__main__': #创建进程池 with ProcessPoolExecutor(50) as t: for i in range(100): t.submit(fun,name=f"进程{i}") #等待进程池中的任务全部执行完毕,才能继续执行 print("已经全部完成!")
二、线程
多线程:
是进程中执行运算的最小单位,是进程中的一个实体。(打开、执行、保存…)
一个程序至少有一个进程,一个进程至少有一个线程。
操作系统分配CPU的基本单位
参考:
from threading import Thread def fun(name): for i in range(1000): print(name,1) if __name__ == '__main__': #创建线程并且给线程安排任务 p_one = Thread(target=fun,args=("第一个子线程",)) p_two = Thread(target=fun,args=("第二个子线程",)) #多线程状态为开始工作状态,具体的执行时间由CPU决定 p_one.start() p_two.start()
线程池:
from concurrent.futures import ThreadPoolExecutor def fun(name): for i in range(1000): print(name,i) if __name__ == '__main__': #创建线程池 with ThreadPoolExecutor(50) as t: for i in range(100): t.submit(fun,name=f"子线程{i}") #等待所有线程全部完成,才会执行下面代码(守护) print("所有线程已经全部完成!!!")
线程池实战
import time from concurrent.futures import ThreadPoolExecutor def download(url,i): time.sleep(2) print(f"第{i}页下载完成!") if __name__ == '__main__': with ThreadPoolExecutor(100) as t: for i in range(1000): url = f"www.mbigfish.com?id={i}" t.submit(download, url, i) print("全部下载完成!")
三、协程
协程结束
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。
一个线程可以拥有多个协程,协程不是被操作系统内核所管理,而完全是由程序所控制。
与其让操作系统调度,不如我自己来,这就是协程
import asyncio import time async def fun1(): print('第一个函数开始') #time.sleep(2) 当程序出现了同步操作的时候,异步就中断了 await asyncio.sleep(2) #异步操作的代码 print('第一个函数结束') async def fun2(): print('第二个函数开始') await asyncio.sleep(2) print('第二个函数结束') async def fun3(): print('第三个函数开始') await asyncio.sleep(4) print('第三个函数结束') async def main(): # 第一种写法 # f1 = fun1() # await fi 一般await挂起操作放在协程对象前面 # 第二中写法(推荐) tasks = [ asyncio.create_task(fun1()), asyncio.create_task(fun2()), asyncio.create_task(fun3()) ] await asyncio.wait(tasks) if __name__ == '__main__': t1 = time.time() asyncio.run(main()) t2 = time.time() print('所需时间:', t2-t1)
协程下载模板
import asyncio import time async def download(url): print(url,'下载开始') await asyncio.sleep(2) print(url,'下载结束') async def main(): urls = [ 'www.a1.com', 'www.a2.com', 'www.a3.com', 'www.a4.com', 'www.a5.com', 'www.a6.com', ] tasks = [] for url in urls: d = asyncio.create_task(download(url)) tasks.append(d) await asyncio.wait(tasks) if __name__ == '__main__': t1 = time.time() asyncio.run(main()) t2 = time.time() print('所需时间:', t2 - t1)
协程下载实战
import asyncio import aiohttp import time async def download(url): name = url.rsplit('/', 1)[1] async with aiohttp.ClientSession() as session: async with session.get(url) as req: # 请求回来了,写入文件 with open(name,'wb') as fp: #读取内容是异步的,需要await挂起 fp.write(await req.content.read()) print(name,'下载完成!') async def main(): urls = [ 'https://pic.quanjing.com/c6/cx/QJ6880697447.jpg', 'https://pic.quanjing.com/3g/lv/QJ6594284520.jpg', 'https://pic.quanjing.com/ng/wd/QJ8166536175.jpg', 'https://pic.quanjing.com/hj/jj/QJ6802044841.jpg', 'https://pic.quanjing.com/tn/6t/QJ9127562743.jpg', 'https://pic.quanjing.com/39/uc/QJ7108531848.jpg', ] tasks = [] for url in urls: d = asyncio.create_task(download(url)) tasks.append(d) await asyncio.wait(tasks) if __name__ == '__main__': t1 = time.time() #asyncio.run(main()) 会报错 loop = asyncio.get_event_loop() loop.run_until_complete(main()) t2 = time.time() print('所需时间:', t2 - t1)