pythonday31
Event事件
Event事件的作用:
用来控制线程的执行
由一些线程去控制另一些线程
from threading import Event
from threading import Thread
import time
#调用Event类实例化一个对象
e = Event()
#若该方法出现在任务中,则False阻塞 #e.wait() #False
#若该方法出现在任务中,则将其他线程的False改为True,进入就绪态与运行态 e.set() #True
def light():
print('红灯...')
time.sleep(1)
#应该开始发送信号,告诉其他线程准备执行
e.set() #将car中的False ---> True
print('绿灯...')
def car(name):
print('等红灯...')
#让所有汽车进入阻塞
e.wait() #False
print(f'{name}启动...')
#让一个light线程任务控制多个car线程任务
t = Thread(target = light)
t.start()
for line in range(10):
t = Thread(target=car,args=(f'CART{line}'))
t.start()
线程池与进程池
什么是进程池与线程池
进程池与线程池是用来控制当前程序允许创建(进程/线程)的数量
进程池与线程池的作用
保证在硬件允许的范围内创建(进程/线程)的数量
代码实现
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
#ProcessPoolExecutor(5) #5代表只能开启5个进程,不填写,默认以CPU的个数限制进程数
pool = ThreadPoolExecutor(5) #代表5个线程,不填写,默认以CPU个数*5限制线程数
def task():
print('任务开始...')
time.sleep(1)
print('任务结束...')
for line in range(5):
pool.submit(task)
回调函数
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
def task(res):
print('任务开始...')
time.sleep(1)
print('任务结束...')
return 123
# 回调函数
def call_back(res):
print(type(res))
res2 = res.result()
print(res2)
for line in range(5):
pool.submit(task, 1).add_done_callback(call_back)
协程
协程的作用
进程:资源单位
线程:执行单位
协程:在单线程下实现并发
attention : 协程不是操作系统资源,它是程序起的名字,为了让单线程能实现并发
协程的目的
操作系统:
操作系统下,线程具有多道技术,切换以及保存线程状态
1. 遇到IO事件
2. 当占用CPU执行时间过长
协程:
通过手动模拟操作系统的'多道技术',实现切换+保存状态
手动实现遇到IO切换
单线程遇到IO,切换+保存状态
单线程计算密集型,来回切换+保存状态效率反而会降低
优点:
在IO密集的情况下,会提高效率
缺点:
若在计算密集的情况下来回切换,效率反而会降低
协程的使用
yield : yiled可以保存状态,yield的状态保存与操作系统的保存线程状态很像,
但是yield是代码级别控制的,更轻量级
并发: 切换
#串行执行
import time
def consumer(res):
'''任务1:接收数据,处理数据'''
pass
def producer():
'''任务2:生产数据'''
res=[]
for i in range(10000000):
res.append(i)
return res
start=time.time()
#串行执行
res=producer()
consumer(res) #写成consumer(producer())会降低执行效率
stop=time.time()
print(stop-start) #1.5536692142486572
#基于yield并发执行
import time
def consumer():
'''任务1:接收数据,处理数据'''
while True:
x=yield
def producer():
'''任务2:生产数据'''
g=consumer()
next(g)
for i in range(10000000):
g.send(i)
start=time.time()
#基于yield保存状态,实现两个任务直接来回切换,即并发的效果
#PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.
producer()
stop=time.time()
print(stop-start)