共计 1717 个字符,预计需要花费 5 分钟才能阅读完成。
咱们晓得,在 Python 外面能够应用 time.sleep 来让代码暂停一段时间,例如:
import time
print('... 局部代码...')
time.sleep(5)
print('... 剩下的代码...')
程序首先打印出 … 局部代码 …,而后期待 5 秒钟,再打印出 … 剩下的代码 …。
当初大家想一想,有没有什么方法,在不应用 time.sleep 的状况下,让程序暂停 5 秒?
你可能会说,用 requests 拜访一个提早 5 秒的网址、或者用递归版算法计算斐波那契数列第 36 位……这些奇技淫巧。
不过明天我说的,是另外一个货色,threading 模块外面的 Event。
咱们来看看它的用法:
import threading
event = threading.Event()
print('... 局部代码...')
event.wait(5)
print('... 剩下的代码...')
这样一来,程序首先打印出 … 局部代码 …,而后期待 5 秒钟,再打印出 … 剩下的代码 …。
性能看起来跟 time.sleep 没什么区别,那为什么我要特地提到它呢?因为在多线程外面,它比 time.sleep 更有用。咱们来看一个例子:
import threading
class Checker(threading.Thread):
def __init__(self, event):
super().__init__()
self.event = event
def run(self):
while not self.event.is_set():
print('查看 redis 是否有数据')
time.sleep(60)
trigger_async_task()
event = threading.Event()
checker = Checker(event)
checker.start()
if user_cancel_task():
event.set()
我来解释一下这段代码的意思。在主线程外面,我调用 trigger_async_task() 触发了一个异步工作。这个工作多久实现我并不分明。然而这个工作实现当前,它会往 Redis 外面发送一条音讯,只有 Redis 有这个音讯了,我就晓得它实现了。所以我要创立一个 checker 子线程,每 60 秒去 Redis 外面查看工作是否实现。如果没有实现,就暂停 60 秒,而后再查看。
但某些状况下,我不须要期待了,例如用户被动勾销了工作。这个时候,我就想提前结束这个 checker 子线程。
然而咱们晓得,线程是不能从里面被动杀死的,只能让它本人退出。所以当我执行 event.set() 后,子线程外面 self.event.is_set() 就会返回 False,于是这个循环就不会继续执行了。
可是,如果某一轮循环刚刚开始,我在主线程外面调用了 event.set()。此时,子线程还在 time.sleep 中,那么子线程须要期待 60 秒才会退出。
但如果我批改一下代码,应用 self.event.wait(60):
import threading
class Checker(threading.Thread):
def __init__(self, event):
super().__init__()
self.event = event
def run(self):
while not self.event.is_set():
print('查看 redis 是否有数据')
self.event.wait(60)
trigger_task()
event = threading.Event()
checker = Checker(event)
checker.start()
if user_cancel_task():
event.set()
那么,即使 self.event.wait(60) 刚刚开始阻塞,只有我在主线程中执行了 event.set(),子线程外面的阻塞立即就会完结。于是子线程立即就会完结。不须要再白白期待 60 秒。
并且,event.wait() 这个函数在底层是应用 C 语言实现的,不受 GIL 锁的烦扰。
以上就是本次分享的所有内容,想要理解更多 python 常识欢送返回公众号:Python 编程学习圈 ,发送“J”即可收费获取,每日干货分享