Tornado:如何启动异步线程

时间:2017-04-29 17:05:42

标签: python multithreading asynchronous tornado

我在这里关注Tornado教程:http://www.tornadoweb.org/en/stable/locks.html#tornado.locks.Condition

现在我想要两个线程等待相同的条件变量,而不是一个服务员。当条件被释放时,我希望线程开始以异步方式工作

我试图这样做:

from time import sleep
from tornado import gen
from tornado.ioloop import IOLoop
from tornado.locks import Condition

condition = Condition()

@gen.coroutine
def waiter():
    print('1: waiting')
    yield condition.wait()  # Yield a Future.
    print('1: finish waiting')
    for i in range(5):
        sleep(1)
        print('1: doing work', i)

@gen.coroutine
def waiter2():
    print('2: waiting')
    yield condition.wait()  # Yield a Future.
    print('2: finish waiting')
    for i in range(5):
        sleep(1)
        print('2: doing work', i)

@gen.coroutine
def notifier():
    print("About to notify")
    sleep(2)
    condition.notify_all()
    print("Done notifying")

@gen.coroutine
def runner():
    # combines the futures
    yield [waiter(), waiter2(), notifier()]

IOLoop.current().run_sync(runner)

然而,在 waiter1退出后,waiter2总是醒来并开始工作。

我还试图两次致电IOLoop.current().run_sync(),但龙卷风抛出RuntimeError: IOLoop has already started.

有人可以告诉我,异步启动线程的正确代码是什么?谢谢!

修改

答案指出sleep应替换为gen.sleep。对于我发布的代码段,这是完全正确的,所以谢谢你。

但是,此处的sleep()仅用于说明目的。我真正想要的是waiter()waiter2()同时进行长时间阻止处理 。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

您无法在代码中调用time.sleep,因为这么长的阻止调用会干扰龙卷风的IOLoop工作方式。将time.sleep的调用替换为tornado.gen.sleep协程,您的代码运行正常:

from time import sleep
from tornado import gen
from tornado.ioloop import IOLoop
from tornado.locks import Condition

condition = Condition()

@gen.coroutine
def waiter():
    print('1: waiting')
    yield condition.wait()  # Yield a Future.
    print('1: finish waiting')
    for i in range(5):
        yield gen.sleep(1)
        print('1: doing work', i)

@gen.coroutine
def waiter2():
    print('2: waiting')
    yield condition.wait()  # Yield a Future.
    print('2: finish waiting')
    for i in range(5):
        yield gen.sleep(1)
        print('2: doing work', i)

@gen.coroutine
def notifier():
    print("About to notify")
    yield gen.sleep(2)
    condition.notify_all()
    print("Done notifying")

@gen.coroutine
def runner():
    # combines the futures
    yield [waiter(), waiter2(), notifier()]

IOLoop.current().run_sync(runner)