Event事件
Event事件
Event事件的作用:
- 用来控制线程的执行.
- 由一些线程去控制另一些线程
from threading import Event
#实例化
e = Event()
#如果出现在线程中,则阻塞(False)
e.wait()
#如果出现在线程中,则则将其他线程中的e.wait()变为True,进入就绪态或运行态
e.set()
from threading import Event
from threading import Thread
import time
def light():
print('红灯亮...')
time.sleep(5)
# 应该开始发送信号,告诉其他线程准备执行
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'童子军jason{line}号', ))
t.start()
线程池和进程池
- 什么是进程池与线程池?
进程池与线程池是用来控制当前程序允许创建(进程/线程)的数量 - 进程池与线程池的作用:
保证在硬件允许的范围内创建 (进程/线程) 的数量
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import time
pool = ThreadPoolExecutor(5)
def task(res):
# res == 1
print('线程任务开始了...')
time.sleep(1)
print('线程任务结束了...')
return 123
#回调函数
def call_back(res):
print(type(res))
# 注意: 赋值操作不要与接收的res同名
res2 = res.result() #res2 = 123 ,即res2等于task的返回值
print(res2)
for line in range(5):
pool.submit(task, 1).add_done_callback(call_back) #异步提交
# 会让所有线程池的任务结束后,才往下执行代码
pool.shutdown()
print('hello')
利用线程池和回调函数爬虫
协程
进程: 资源单位
- 线程: 执行单位
- 协程: 在单线程下实现并发
注意: 协程不是操作系统资源,他是程序起的名字,为让单线程能实现并发.
协程的目的:
- 操作系统:
多道技术, 切换 + 保存状态
1) 遇到IO
2) CPU执行时间过长协程:
通过手动模拟操作系统 "多道技术",实现 切换 + 保存状态
1)手动实现 遇到IO切换, 欺骗操作系统误以为没有IO操作.
- 单线程 遇到IO, 切换 + 保存状态- 单线程 计算密集型, 来回切换 + 保存状态是,反而效率更低
优点:
在IO密集型的情况下, 会提高效率.缺点:
若在计算密集型的情况下, 来回切换, 反而效率更低
from gevent import monkey
monkey.patch_all() # 可以监听该程序下所有的IO操作
import time
from gevent import spawn, joinall # 用于做切换 + 保存状态
def func1():
print('1')
# IO操作
time.sleep(1)
def func2():
print('2')
time.sleep(3)
def func3():
print('3')
time.sleep(5)
start_time = time.time()
s1 = spawn(func1)
s2 = spawn(func2)
s3 = spawn(func3)
# s2.join() # 发送信号,相当于等待自己 (在单线程的情况下)
# s1.join()
# s3.join()
# 必须传序列类型
joinall([s1, s2, s3])
end_time = time.time()
print(end_time - start_time)