Tornado 中在子线程执行耗时操作导致的主线程阻塞问题及解决方案

在 Tornado 中,如果在子线程中运行一个耗时操作(例如进行数据查询或文件读写),可能会导致主线程阻塞,从而无法处理其他请求。这是因为 Tornado 使用的是单线程模型,所有的请求都由主线程来处理。如果主线程被阻塞,那么其他请求就无法得到处理。
在这里插入图片描述

2、解决方案

为了避免主线程阻塞,我们可以使用以下几种方法:

  • 方法一:使用 ThreadPoolExecutor

ThreadPoolExecutor 是 Python 内置的线程池库,我们可以使用它来创建多个线程,并将耗时操作分配给这些线程来执行。这样,主线程就可以继续处理其他请求,而不会被阻塞。

from concurrent.futures import ThreadPoolExecutor

def long_blocking_function(index, sleep_time):
    print ("Entering run counter:%s" % (index,))
    time.sleep(sleep_time)
    print ("Exiting run counter:%s" % (index,))
    return "Result from %d" % index


class FooHandler(tornado.web.RequestHandler):
    executor = ThreadPoolExecutor(max_workers=10)

    @tornado.gen.coroutine
    def get(self):
        global counter
        counter += 1
        current_counter = str(counter)

        print ("ABOUT to spawn thread for counter:%s" % (current_counter,))
        result = yield self.executor.submit(long_blocking_function,
                                            index=current_counter,
                                            sleep_time=5)
        self.write(result)
        print ("DONE with the long function")
  • 方法二:使用 AsyncHTTPClient

AsyncHTTPClient 是 Tornado 内置的异步 HTTP 客户端库,我们可以使用它来进行网络请求。这样,网络请求就可以在子线程中执行,而不会阻塞主线程。

import tornado.httpclient

def long_blocking_function(index, sleep_time):
    print ("Entering run counter:%s" % (index,))
    time.sleep(sleep_time)
    print ("Exiting run counter:%s" % (index,))
    return "Result from %d" % index


class FooHandler(tornado.web.RequestHandler):
    http_client = tornado.httpclient.AsyncHTTPClient()

    @tornado.gen.coroutine
    def get(self):
        global counter
        counter += 1
        current_counter = str(counter)

        print ("ABOUT to spawn thread for counter:%s" % (current_counter,))
        response = yield self.http_client.fetch("http://example.com")
        self.write(response.body)
        print ("DONE with the long function")
  • 方法三:使用 asyncio

asyncio 是 Python 内置的异步 I/O 库,我们可以使用它来编写异步代码。这样,我们可以将耗时操作包装成一个协程,并在子线程中执行它,而不会阻塞主线程。

import asyncio

def long_blocking_function(index, sleep_time):
    print ("Entering run counter:%s" % (index,))
    yield asyncio.sleep(sleep_time)
    print ("Exiting run counter:%s" % (index,))
    return "Result from %d" % index


class FooHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        global counter
        counter += 1
        current_counter = str(counter)

        print ("ABOUT to spawn thread for counter:%s" % (current_counter,))
        result = yield long_blocking_function(current_counter, 5)
        self.write(result)
        print ("DONE with the long function")
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值