• python-中断time.sleep一种更优雅的办法:event.wait


    场景描述:

    实现一个功能,启动一个线程,只要线程不中断,就一直while true,间断10s累加某个数;

    当线程线程信号时,while停止,线程退出。

    1、方法一 time.sleep

    1. import time
    2. from threading import Thread
    3. class AddTask(Thread):
    4. def __init__(self):
    5. super().__init__()
    6. self.sum_num = 0
    7. self._button = True
    8. def run(self):
    9. print('Begin to add ...')
    10. while self._button:
    11. print('Sleep start...')
    12. time.sleep(10)
    13. print('Sleep end...')
    14. self.sum_num += 10
    15. print(f"Finish add, sum:{self.sum_num}...")
    16. def stop(self):
    17. print('Stop task...')
    18. self._button = False
    19. def do_main_task():
    20. print('Do main task...')
    21. time.sleep(15)
    22. print('Finish main task...')
    23. return True
    24. if __name__ == '__main__':
    25. add_task = AddTask()
    26. add_task.start()
    27. main_task_end = do_main_task()
    28. if main_task_end:
    29. add_task.stop()
    30. time.sleep(1)
    31. print(f"sum: {add_task.sum_num}")

    执行结果:

    Begin to add ...Do main task...
    Sleep start...
    Sleep end...
    Sleep start...
    Finish main task...
    Stop task...
    sum: 10
    Sleep end...
    Finish add,sum: 20...

    解释一下这段代码的意思。在主线程里面,我调用do_main_task()触发了一个任务。这个任务执行会久一些(这里设定15s)。但是这个任务完成以后,会有个返回值,告诉我完成了。另外创建一个 add_task 子线程,每10秒累加10。

    但某些情况下,我不需要等待了,例如用户主动取消了任务。这个时候,我就想提前结束这个 add_task 子线程。

    通过执行结果可以看出,当执行一次+10,等待10s后,又过了5秒,主线程do_main_task结束了,这时add_task线程还在累加的sleep(10)中没有退出。主线程执行结果已经是sum=10,再过5秒后add_task线程才结束。

    但是,线程是不能从外面主动杀死的,只能让它自己退出。

    2、方法二 event.wait

    应用threading模块里面的Event,

    用法和sleep差不多:

    1. import threading
    2. event = threading.Event()
    3. event.wait(5)

    上述例子可以这样实现:

    1. import time
    2. from threading import Thread
    3. from threading import Event
    4. class AddTask(Thread):
    5. def __init__(self):
    6. super().__init__()
    7. self.sum_num = 0
    8. self.event = Event()
    9. def run(self):
    10. print('Begin to add ...')
    11. while not self.event.is_set():
    12. print('Sleep start...')
    13. self.event.wait(10)
    14. print('Sleep end...')
    15. self.sum_num += 10
    16. print(f"Finish add, sum:{self.sum_num}...")
    17. def stop(self):
    18. print('Stop task...')
    19. self.event.set()
    20. def do_main_task():
    21. print('Do main task...')
    22. time.sleep(15)
    23. print('Finish main task...')
    24. return True
    25. if __name__ == '__main__':
    26. add_task = AddTask()
    27. add_task.start()
    28. main_task_end = do_main_task()
    29. if main_task_end:
    30. add_task.stop()
    31. time.sleep(1)
    32. print(f"sum: {add_task.sum_num}")

    执行结果:

    Do main task...
    Begin to add ...
    Sleep start...
    Sleep end...
    Sleep start...
    Finish main task...
    Stop task...
    Sleep end...
    Finish add, sum:20...

    sum: 20

    当执行event.set()后,子线程里面self.event.is_set()就会返回 False,于是这个循环就不会继续执行了。

    即使self.event.wait(10)刚刚开始阻塞,只要我在主线程中执行了event.set(),子线程里面的阻塞立刻就会结束。于是子线程立刻就会结束。不需要再白白等待10秒。

    并且,event.wait()这个函数在底层是使用 C 语言实现的,不受 GIL 锁的干扰。

     

  • 相关阅读:
    FaceChain-FACT:免训练的丝滑体验,秒级别的人像生成
    软考高级之系统架构设计师系列【2】考试说明及考点分析
    js介绍及内置功能函数、数据类型、变量
    JDK下载安装以及不同版本JDK在同一电脑上随意切换
    [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
    2024-安装VMware® Workstation 17 Pro
    4.2 Serializable Concept(3)
    js建树、遍历操作
    20230916后台面经整理
    uniapp 微信小程ios端键盘弹起后导致页面无法滚动
  • 原文地址:https://blog.csdn.net/qq_19446965/article/details/126793548