doraemon的python 协程

### 9.8 协程

进程、线程、协程三者的区别:

- 进程:是资源分配最小的单位
- 线程:是CPU执行的最小单位
- 协程:用户级别的,由我们自己写的python代码来控制切换的,操作系统不可见

协程的意义:

```python
#在Cpython解释器下 - 协程和线程都不能利用多核,都是在一个CPU上轮流执行
    # 由于多线程本身就不能利用多核
    # 所以即便是开启了多个线程也只能轮流在一个CPU上执行
    # 协程如果把所有任务的IO操作都规避掉,只剩下需要使用CPU的操作
    # 就意味着协程就可以做到题高CPU利用率的效果
```

多线程和协程:

```python
# 线程 切换需要操作系统,开销大,操作系统不可控,给操作系统的压力大
    # 操作系统对IO操作的感知更加灵敏
# 协程 切换需要python代码,开销小,用户操作可控,完全不会增加操作系统的压力
    # 用户级别能够对IO操作的感知比较低
    
注意:我们写的协程只能切换我们能够感知到的IO操作,但是对于无法感知的IO操作依然需要依赖线程
```

#### 9.8.1 gevent模块

```python
import time
import gevent
from gevent import monkey #本来gevent模块不认识time模块,这个帮助识别
monkey.patch_all()
def eat():
    print('liujia is eating')
    time.sleep(1)
    print('liujia finished eat')
    
def sleep():
    print('liudanni is sleep')
    time.sleep(1)
    print('liudanni finised')
    
g1 = gevent.spawn(eat)  #创造一个协程任务,遇到IO操作就自动切换
g2 = gevent.spawn(sleep)
g1.join()  #阻塞,直到g1任务完成为止 如果不阻塞切换了就不会切换回来了
g2.join()
gevent.joinall([g1,g2]) #将要阻塞的统一放进来阻塞
print(g1.value)  #取结果
#开启10个协程
g_l = []
for i inrange(10):
    g = gevent.spawn(eat)
    g_l.append(g)
gevent.joinall(g_l)
```

#### 9.8.2 asyncio模块

```python
#启动一个任务
async def demo():   #协程方法
    print('start')
    await asyncio.sleep(1) #阻塞
    print('end')
    
loop = asyncio.get_event_loop() #创建一个时间循环
loop.eun_until_complete(demo()) #把demo任务丢到时间循环中去执行
```

```python
#地洞多个任务,并且没有返回值
async def demo():   # 协程方法
    print('start')
    await asyncio.sleep(1)  # 阻塞
    print('end')

loop = asyncio.get_event_loop()  # 创建一个事件循环
wait_obj = asyncio.wait([demo(),demo(),demo()])
loop.run_until_complete(wait_obj)
```

```python
#启动多个任务并且有返回值
async def demo():   # 协程方法
    print('start')
    await asyncio.sleep(1)  # 阻塞
    print('end')
    return 123

loop = asyncio.get_event_loop()
t1 = loop.create_task(demo())
t2 = loop.create_task(demo())
tasks = [t1,t2]
wait_obj = asyncio.wait([t1,t2])
loop.run_until_complete(wait_obj)
for t in tasks:
    print(t.result())

```

```python
#谁先回来先取谁的结果
import asyncio
async def demo(i):   # 协程方法
    print('start')
    await asyncio.sleep(10-i)  # 阻塞
    print('end')
    return i,123

async def main():
    task_l = []
    for i in range(10):
        task = asyncio.ensure_future(demo(i))
        task_l.append(task)
    for ret in asyncio.as_completed(task_l):
        res = await ret
        print(res)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

```

猜你喜欢

转载自www.cnblogs.com/doraemon548542/p/11442743.html