一日一技:除了 time.sleep,你还有一个暂停代码的方法

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 一日一技:除了 time.sleep,你还有一个暂停代码的方法

摄影:产品经理里面的鱼子滑得咬不到

我们知道,在 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 锁的干扰。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2天前
sleep()和wait()的区别
(1)wait()是Object的方法,sleep()是Thread类的方法 (2)wait()会释放锁,sleep()不会释放锁 (3)wait()要在同步方法或者同步代码块中执行,sleep()没有限制 (4)wait()要调用notify()或notifyall()唤醒,sleep()自动唤醒
13 5
|
1月前
|
前端开发 JavaScript
前端:实现一个 sleep 函数
在前端开发中,实现一个 `sleep` 函数可以用来暂停代码执行,模拟延迟效果,常用于测试或控制异步操作的节奏。该函数通常基于 `Promise` 和 `setTimeout` 实现,简单易用。
|
6月前
|
存储 弹性计算 运维
sleep命令
【4月更文挑战第29天】
33 0
|
6月前
|
Unix 程序员 编译器
C++ Sleep 函数
C++ Sleep 函数
241 1
|
11月前
|
网络协议 Cloud Native
为什么需要 TIME_WAIT 状态
为什么需要 TIME_WAIT 状态
为什么需要 TIME_WAIT 状态
sleep () 和 wait () 的区别
sleep () 和 wait () 的区别
89 0
|
监控
Sleep()和wait()方法的区别
Sleep()和wait()方法的区别
136 0
|
Java 程序员
sleep 和 wait 的区别
Java 中,线程的 "sleep" 和 "wait" 方法区别
129 0
|
Python
一日一技:为什么不建议使用 time.sleep 实现定时功能?
一日一技:为什么不建议使用 time.sleep 实现定时功能?
165 0
|
Python
[oeasy]python0026_刷新时间_延迟时间_time_sleep_死循环_while_True
[oeasy]python0026_刷新时间_延迟时间_time_sleep_死循环_while_True
103 0
[oeasy]python0026_刷新时间_延迟时间_time_sleep_死循环_while_True