当前位置: 首页 > 后端技术 > Python

Python多线程技巧:比time.sleep更好的暂停方式!

时间:2023-03-26 19:17:54 Python

我们知道在Python中可以使用time.sleep让代码暂停一段时间,例如:importtimeprint('...partofthecode...')time.sleep(5)print('...remainingThecodebelow...')程序首先打印出...部分代码...,然后等待5秒,然后打印出...剩余的代码....现在想一想,有没有什么办法可以不使用time.sleep,让程序暂停5秒呢?你可能会说使用延迟5秒的请求访问URL,或者使用递归版本的算法来计算斐波那契数列的第36位……这些技巧。不过今天要说的是另外一个东西,threading模块中的Event。我们来看看它的用法:importthreadingevent=threading.Event()print('...部分代码...')event.wait(5)print('...其余代码...')这样,程序首先打印出......部分代码......,然后等待5秒,然后打印出......其余代码......功能看起来与时间没有什么不同。睡觉,我为什么要特别提到它呢?因为在多线程中,它比time.sleep更有用。让我们看一个例子::print('检查redis是否有数据')time.sleep(60)trigger_async_task()event=threading.Event()checker=Checker(event)checker.start()ifuser_cancel_task():event.set()我会解释这段代码的含义。在主线程中,我调用trigger_async_task()来触发一个异步任务。这个任务不知道要多久才能完成。但是这个任务完成后,它会向Redis发送消息。只要Redis有这个消息,就知道完成了。所以我想创建一个检查器子线程,每隔60秒去Redis检查任务是否完成。如果没有完成,请暂停60秒并再次检查。但有些情况下,我不需要等待,比如用户主动取消了任务。这时,我想早点结束这个检查子线程。但是我们知道一个线程是不能从外面主动杀掉的,只能让它自己退出。所以当我执行event.set()时,子线程中的self.event.is_set()会返回False,所以循环就不会继续执行了。但是,如果某个循环刚刚开始,我会在主线程中调用event.set()。这时候子线程还在time.sleep,那么子线程需要等待60秒才能退出。但是,如果我修改代码以使用self.event.wait(60):):whilenotself.event.is_set():print('检查redis是否有数据')self.event.wait(60)trigger_task()event=threading.Event()checker=Checker(event)checker.start()ifuser_cancel_task():event.set()那么,即使self.event.wait(60)刚开始阻塞,只要我在主线程中执行event.set(),子线程中的阻塞将立即结束。所以子线程会立即结束。无需白等60秒。而且event.wait()函数在底层是用C语言实现的,没有GIL锁的干扰。以上就是本次分享的全部内容。想了解更多python知识,请前往公众号:Python编程学习圈,发“J”免费领取,每日干货分享