(day31) Event+协程+进程/线程池
2024-09-01 08:09:20
目录
昨日回顾
GIL全局解释器锁
- 本质上是互斥锁
- Cpython才有的
- 同一个进程下开启多个线程,让并发变成串行,保证线程安全
计算密集型和IO密集型
计算密集型
使用多进程
IO密集型
使用多线程
死锁现象
两个锁在两个或多个线程或进程中被相互调用,从而陷入相互等待的现象
递归锁
解决死锁问题,相当于串在一起的锁,只有在递归锁的引用计数为0 ,才能被使用
信号量
相当于锁店,设置多少个就能被多少个线程或进程使用
线程队列
FOFI队列
先进先出
LIFO队列
后进先出
优先级队列
按照从左到右,根据数字/acsii大小,越小,优先级越高
今日内容
Event事件
控制线程的执行,由一些线程去控制另一些线程
当Event对象为False时,该线程会被阻塞,直至Event对象为真,相当于红绿灯的作用
isSet():返回Event对象的状态
wait():判断Event对象的状态,若为Flase,则阻塞
Set():设置Event对象为Ture
clear():恢复Event对象为False
from threading import Event
from threading import Thread
import time
e = Event()
def light():
print('红灯亮')
time.sleep(5)
print('绿灯亮')
e.set()
def car():
print('等红灯中...')
e.wait()
print('车辆加速中')
t = Thread(target=light)
t.start()
for i in range(20):
a = Thread(target=car)
a.start()
线程池与进程池
- 进程池和线程池是用来控制当前程序允许创建的进程或线程的数量
- 保证在硬件允许的范围内创建进程/线程的数量
异步提交和回调函数
可以为进程池或线程池内的每个进程或线程绑定一个函数,该函数在进程或线程的任务执行完毕后自动触发,并接收任务的返回值当作参数,该函数称为回调函数
ProcessPoolExecutor(5) # 5代表只能开启5个进程
ProcessPoolExecutor() # 默认以CPU的个数限制进程数
ThreadPoolExecutor() # 默认以CPU个数 * 5 限制线程数
pool.shutdown() # 会让所有线程池的任务结束后,才往下执行代码
pool.submit('传函数地址') # 异步提交任务
pool.submit('传函数地址').add_done_callback('回调函数地址') # 回调函数
import time
# from concurrent.futures import ProcessPoolExecutor
from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor(5)
def task(res):
print('线程任务开始')
time.sleep(1)
print('线程任务结束')
return res
def call_back(res):
res1 = res.result()
print(res1)
for i in range(5):
pool.submit(task,i).add_done_callback(call_back)
协程
协程:在单线程下实现并发,不是操作系统资源
通过手动模拟遇到IO切换,欺骗操作系统误以为没有进程IO操作,从而实现在程序层面的并发( 切换+保存状态)
- 优点:IO密集型情况下,会提高效率
缺点:若在计算密集型的情况下,来回切换,反而效率更低
yiled
无法检测IO,无法实现遇到IO自动切换
# 串行执行
import time
def func1():
for i in range(10000000):
i+1
def func2():
for i in range(10000000):
i+1
start = time.time()
func1()
func2()
stop = time.time()
print(stop - start) # 0.8930509090423584
# 验证计算密集型的情况下效率更低: # 1.4250171184539795
# 基于yield并发执行
import time
def func1():
while True:
10000000+1
yield
def func2():
# g生成器对象
g = func1()
for i in range(10000000):
time.sleep(100) # 模拟IO,yield并不会捕捉到并自动切换
i+1
next(g)
start = time.time()
func2()
stop = time.time()
print(stop-start)
gevent模块
第三方模块,可以监听IO操作,并实现切换 + 保存状态
from gevent import spawn,joinall # 用于做切换 + 保存状态
from gevent import monkey # 可以监听该程序下所有的IO操作
monkey.patch_all()
import time
def func1():
print('1')
time.sleep(1)
def func2():
print('2')
time.sleep(2)
def func3():
print('3')
time.sleep(3)
start = time.time()
s1=spawn(func1)
s2=spawn(func2)
s3=spawn(func3)
# 必须传序列类型
joinall((s1,s2,s3))
end = time.time()
print(end - start)
最新文章
- 第六百一十六天 how can I 坚持
- Oracle计算时间差表达式
- Cannot install NodeJs: /usr/bin/env: node: No such file or directory
- 设计模式之Builder (创建者模式)的一些个人理解(转)
- chrome http Request Header 修改插件
- 双4G LTE
- LayoutInflater和inflate()方法的用法
- ORM之PetaPoco错误--VS中NUGet程序包管理安装PetaPoco
- Remove Duplicates from Sorted List II 解答
- 正确AJAX了解该技术的,创建,应用
- python算法-选择排序
- Lintcode487-Name Deduplication-Easy
- PMP学习总结(1) -- 引论
- TensorFlow+Keras 02 深度学习的原理
- wx.downloadFile问题
- 高性能NIO框架Netty-对象传输
- PyCharm配置MySQL
- 1. apache如何启动
- ORACLE判断两个日期间隔几个工作日
- Juicer自定义函数
热门文章
- MySQL中四种隔离级别的演示
- Spring MVC-从零开始-@RequestMapping 注解method属性
- 深入理解 DeepSea 和 Salt 部署工具 - Storage6
- dubbo-spring-boot的auto-configure示例报Not found exported service的解决办法
- H5刮刮卡效果
- wordpress安装主题、插件需要FTP用户名密码
- ping本地局域网
- 【linux】jdk安装及环境变量配置
- Spring Boot 2.X(八):Spring AOP 实现简单的日志切面
- 《Java编程思想》——初始化与清理(一)读书笔记