进程,线程,协程概念简述
多进程:对系统的cup资源进行最大的利用
多线程:对系统分配给当前进程的cup资源进行最大限度的运用
window 核心是主多线程 liunx核心主是多进程,每一个请求开出一个进程
可用将多进程理解为多个人多张桌子吃饭
多线程可用理解为多个人在同一张桌子吃饭
进程是系统资源分配的基本单位,线程是进程资源分配的基本单位
协程,又称微线程,纤程,英文名Coroutine。协程的作用是在执行函数A时可以随时中断去执行函数B,然后中断函数B继续执行函数A(可以自由切换)。但这一过程并不是函数调用,这一整个过程看似像多线程,然而协程只有一个线程执行
协程与线程的区别
- 由于协程的特性, 适合执行大量的I/O 密集型任务, 而线程在这方面弱于协程
- 协程涉及到函数的切换, 多线程涉及到线程的切换, 所以都有执行上下文, 但是协程不是被操作系统内核所管理, 而完全是由程序所控制(也就是在用户态执行), 这样带来的好处就是性能得到了很大的提升, 不会像线程那样需要在内核态进行上下文切换来消耗资源,因此协程的开销远远小于线程的开销
- 同一时间, 在多核处理器的环境下, 多个线程是可以并行的,但是运行的协程的函数却只能有一个,其他的协程的函数都被suspend, 即协程是并发的
- 由于协程在同一个线程中, 所以不需要用来守卫临界区段的同步性原语(primitive)比如互斥锁、信号量等,并且不需要来自操作系统的支持
- 在协程之间的切换不需要涉及任何系统调用或任何阻塞调用
- 通常的线程是抢先式(即由操作系统分配执行权) , 而协程是由程序分配执行权
那协程有什么优势呢?
- 执行效率极高,因为子程序切换(函数)不是线程切换,由程序自身控制,没有切换线程的开销。所以与多线程相比,线程的数量越多,协程性能的优势越明显。
- 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在控制共享资源时也不需要加锁,因此执行效率高很多
多任务异步协程套路(主要用requests 进行url获取,aiohttp对url进行异步解析)
async
用来声明一个函数为异步函数,异步函数的特点是能在函数执行过程中挂起,去执行其他异步函数,等到挂起条件
async 可以将函数变为一个特殊函数(1,该特殊函数被调用后,函数内部不会立即执行。2,该函数被调用后会返回一个协程对象。3,协程即一组指定的操作。4,任务对象就是高级协程对象)
await
用来用来声明程序挂起,比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序(耗时认为都建议挂起
协程案例
python 源码
import asyncio
import requests
import time
async def result(url):
res = await request_url(url)
print(url, res)
async def request_url(url):
res = requests.get(url, proxies={'https': None, 'http': None}, verify=False)
print(url)
await asyncio.sleep(2)
print("execute_time:", time.time() - start)
return res
url_list = ["www.csdn.net/",
]
start = time.time()
print(f"start_time:{start}\n")
task = [result(url) for url in url_list]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
endtime = time.time() - start
print("\nendtime:", time.time())
print("all_execute_time:", endtime)
import requests ,asyncio,time,aiohttp (支持异步的网络请求模块)
urls=['www.baidu.com','www.hao123.com','www.bing.com']
async def get_request(url):
async with aiohttp.ClientSession() as sess:
async with sess.get(url=url) as response:
page_text=await response.text()
return page_text
if name == 'main':
start=time.time()
tasks=[]
for url in urls:
c=get_request(url)
task=asyncio.ensure_future(c)(创建任务对象)
tasks.append(task)
loop=asyncio.get_event_loop() (注册事件循环,可以将多个任务对象注册或装载到时间循环对象中,开启事件循环,其内部任务则会被基于异步进行执行)
loop.run_until_complete(asyncio.wait(tasks))(注册和启动)
print('总耗时:',time.time()-start)
import threading
import asyncio
async def myfun(index):
print(f'[{index}]({threading.currentThread().name})')
await asyncio.sleep(1)
return index
def getfuture(future):
print(future.result())
loop = asyncio.get_event_loop()
tasks = []
for item in range(10):
future = asyncio.ensure_future(myfun(item))
tasks.append(future)
future.add_done_callback(getfuture)
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
D:\项目文件\python.exe D:\项目文件\new_project\XM\spider\demo.py
0
2
6
9
8
5
7
4
1
3
Process finished with exit code 0
简单总结
进程是资源分配的单位
线程是操作系统调度的单位
进程切换需要的资源很最大,效率很低
线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
协程切换任务资源很小,效率高
多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发