Tornado协程并发

文章探讨了在Python3.8和Tornado6.4环境中,不同类型的异步和同步代码执行效率,包括正常和非正常使用await的情况,以及如何正确利用线程池和协程池优化异步处理。
摘要由CSDN通过智能技术生成

测试版本:Python3.8 Torando6.4

1、非正常异步代码-实际同步:

async def sl():
    time.sleep(0.2)  # 同步等待 2 秒

class AsyncSleepHandler(tornado.web.RequestHandler):
    async def post(self):
        await sl()
        self.write("Async sleep completed!")
结论

顺序输出,50次用时10s,原因是异步函数中存在同步函数,await时按同步处理


2、非正常异步代码-跳过等待:

async def sl():
    time.sleep(0.2)  # 同步等待 2 秒

class AsyncSleepHandler(tornado.web.RequestHandler):
    async def post(self):
        sl()
        self.write("Async sleep completed!")
结论

瞬间输出(0.06s<<0.2s),存在警告,sl()未await,即跳过等待


3、正常异步代码:

class AsyncSleepHandler(tornado.web.RequestHandler):
    async def post(self):
        await asyncio.sleep(0.2)  # 异步等待
        self.write("Async sleep completed!")
结论

0.2s输出,50次用时0.2s,标准异步实现


4、正常同步代码:

class SyncSleepHandler(tornado.web.RequestHandler):
    def post(self):
        time.sleep(0.2)  # 同步等待 2 秒
        self.write("Sync sleep completed!")
结论

50次用时10s,同步实现,等时间距离逐个输出


4.5、同步代码中插入await:

class SyncSleepHandler(tornado.web.RequestHandler):
    async def post(self):
        time.sleep(0.2)  # 同步等待 2 秒
        await asyncio.sleep(0.2)  # 异步等待
        self.write("Sync sleep completed!")
结论

50次用时10.4s,同步实现,集中阻塞返回(偶尔有单个先返回)。表现为await多个请求,最糟糕。正确方法见7.5


5、正常异步代码-借助线程池:

from concurrent.futures import ThreadPoolExecutor
import tornado.web

executor = ThreadPoolExecutor()

def blocking_sleep():
    time.sleep(0.2)  # 同步等待 0.2 秒

async def sl():
    await tornado.ioloop.IOLoop.current().run_in_executor(executor, blocking_sleep)

class AsyncSleepHandler(tornado.web.RequestHandler):
    async def post(self):
        await sl()
        self.write("Async sleep completed!")
结论

50次用时0.6s(受限于线程池大小),借助线程池实现异步调用,适合cpu密集任务


6、非正常异步代码-借助协程池-跳过等待

import asyncio
import tornado.web

async def blocking_sleep():
    time.sleep(0.2)  # 同步等待 0.2 秒

class AsyncSleepHandler(tornado.web.RequestHandler):
    async def post(self):
        await asyncio.get_running_loop().run_in_executor(None, blocking_sleep)
        self.write("Async sleep completed!")
结论

50次用时0.06s(<<0.2s),非正确使用协程池,函数跳过等待


7、正常异步代码-借助协程池

class AsyncSleepHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.executor = tornado.concurrent.futures.ThreadPoolExecutor()

    @tornado.concurrent.run_on_executor  # 同步的阻塞函数转换为异步操作,并在协程池中执行。
    def sl(self):
        time.sleep(0.2)  # 同步等待 0.2 秒

    async def post(self):
        await self.sl()
        self.write("Async sleep completed!")

    def on_finish(self):
        self.executor.shutdown(wait=False)
结论

50次用时0.26s(~0.2s),正确使用协程池,适合IO密集任务


7.5、异步代码插入同步函数-借助协程池

import threading

# 创建一个锁对象
lock = threading.Lock()

class SyncSleepHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.executor = tornado.concurrent.futures.ThreadPoolExecutor()

    def on_finish(self):
        self.executor.shutdown(wait=False)
        
    @tornado.concurrent.run_on_executor()
    def blocking_sleep(self):
        with lock: # 防止资源竞争
            time.sleep(0.2)  # 同步等待 0.2 秒
            
    async def post(self):
        await self.blocking_sleep()  # 同步等待 2 秒
        await asyncio.sleep(0.2)  # 异步等待
        self.write("Sync sleep completed!")
结论

50次用时10.6s


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值