我已经编写了我的问题的示例代码。输入消息被分成固定的 block ,并使用有意的随机延迟进行混合。但是,sleep()
处于阻塞状态,不会运行下一个任务。这在单线程上可行还是必须诉诸多线程?
from random import randint
from time import sleep
def delay_message(split_message, delay):
#sleep(delay) #this blocks
print("Shuffled message: {} and time: {}". format(split_message, delay))
def main():
message = raw_input('Input: ')
#padding
difference = len(message) % 5
message=message.ljust(len(message)+5-difference, "0")
for i in range(0, len(message), 5):
delay = randint(0, 5)
split_message = message[i:i+5]
delay_message(split_message, delay)
if __name__ == "__main__":
main()
最佳答案
sleep
确实会阻塞其正在运行的线程。
可以通过使用像gevent
这样的库使其成为非阻塞的。 。 Gevent 还可以修补 time.sleep 并使其成为非阻塞,并且也有自己的非阻塞 sleep 。它还可以修补整个 python 标准库,使其成为非阻塞 - 套接字、时间、线程等,请参阅 documentation .
上面的例子可以与 gevent 协同并发,如下所示:
from random import randint
from gevent import sleep, spawn, joinall
def delay_message(split_message, delay):
# Gevent's sleep yields the event loop for
# duration of delay rather than blocking the running thread
sleep(delay)
print("Shuffled message: {} and time: {}". format(split_message, delay))
def main():
message = raw_input('Input: ')
#padding
difference = len(message) % 5
message=message.ljust(len(message)+5-difference, "0")
greenlets = []
# This will create len(message)/5 number of greenlets,
# which corresponds to the concurrency level.
# Greenlets all run under one thread so there is no CPU
# overhead here.
for i in range(0, len(message), 5):
delay = randint(0, 5)
split_message = message[i:i+5]
greenlets.append(spawn(delay_message, split_message, delay))
# Wait for all greenlets to complete, raise any exceptions
joinall(greenlets, raise_error=True)
if __name__ == "__main__":
main()
限制是 CPU 密集型任务不能在 greenlet 中运行,因为它们会阻塞事件循环和所有其他 greenlet。
只要 greenlet 中运行的内容是 I/O 绑定(bind)的,例如在套接字或生成器、其他 greenlet 等中传递消息,greenlet 都是合适的。对于 CPU 密集型任务,请使用 native 线程或多进程。
还有其他替代方案,例如 asyncio
(仅限 Py3)。 Gevent 与 Py2 和 3 兼容,并且具有非常高的性能,并由 native 代码扩展支持。
关于python - 如何在Python中异步非阻塞调度任务或事件触发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44592528/