【发布时间】:2015-02-12 13:08:25
【问题描述】:
我需要一个可以中止的sleep() 方法(如here 或here 所述)。
我的方法是让threading.Event.wait() 在指定的持续时间内超时:
def abortable_sleep(secs, abort_event):
abort_event.wait(timeout=secs)
abort_event.clear()
在调用 abortable_sleep(10, _abort) 之后,我现在可以(从另一个线程)调用 _event.set(_abort) 让 abortable_sleep() 在 10 秒之前终止。
例子:
def sleeping_thread():
_start = time.perf_counter()
print("%f thread started" % (time.perf_counter() - _start))
abortable_sleep(5, _abort)
print("%f thread stopped" % (time.perf_counter() - _start))
if __name__ == '__main__':
_abort = threading.Event()
while True:
threading.Thread(target=sleeping_thread).start()
time.sleep(3)
_abort.set()
time.sleep(1)
输出:
0.000001 thread started
3.002668 thread stopped
0.000002 thread started
3.003014 thread stopped
0.000001 thread started
3.002928 thread stopped
0.000001 thread started
此代码按预期工作,但我仍有一些问题:
- 难道没有一种更简单的方式来获得某物吗? likea
sleep()可以中止吗? - 这可以做到更优雅吗?例如。这样我必须小心
Event实例,它没有绑定到abortable_sleep()的实例 - 我是否必须预料到像
while True: abortable_sleep(0.0001)这样的高频循环会出现性能问题? wait()-timeout 是如何实现的?
【问题讨论】:
-
在我看来这或多或少是正确的方法。这取决于您在调用 _abort 时想要发生什么。你想让所有休眠的线程都被唤醒吗?您想要唤醒其中一个线程吗?你想中止特定的线程吗?根据答案,您可能想要使用不同的模型(条件?),或者您可能想要使用线程本地存储来保存 _abort 事件或子类化 Thread 类以保存 _abort 对象。
-
re:第 1 点 - 可能不是。至于第 2 点 - 您应该继承
Thread并封装此行为。 -
abortable_sleep(0.0001):这总会有问题,无论是否中止。您要求睡 100 我们,但线程调度程序可能要等很久之后才能唤醒您。 -
还有竞争条件。如果其他线程在您完成睡眠并清除它之后设置事件,您将遇到问题。你可以在睡觉前打电话给
event.clear(),但这只会缩短危险窗口。
标签: python thread-sleep