time.sleep vs asyncio.sleep 详解

time.sleep vs asyncio.sleep 详解

概述

time.sleepasyncio.sleep 都是用于暂停程序执行的函数,但它们的工作原理完全不同:

特性 time.sleep asyncio.sleep
类型 同步阻塞函数 异步协程函数
阻塞范围 阻塞整个线程 只阻塞当前协程
使用方式 直接调用 必须用 await 调用
适用场景 同步代码/多线程 异步代码/事件循环
并发性能 阻塞期间无法处理其他任务 释放控制权,允许其他任务运行

1. time.sleep - 阻塞式延迟

工作原理

import time

def sync_task():
    print("开始执行")
    time.sleep(3)  # 阻塞整个线程3秒
    print("执行完成")

执行流程

┌─────────────────────────────────────┐
│         线程状态                     │
├─────────────────────────────────────┤
│  [运行] print("开始执行")            │
│       ↓                             │
│  [阻塞中] ████████████████ (3秒)     │  ← 线程完全被占用
│       ↓                             │
│  [运行] print("执行完成")            │
└─────────────────────────────────────┘

特点

  • ✅ 简单直接,易于理解
  • 阻塞整个线程,线程无法执行其他任务
  • ❌ 在异步函数中使用会阻塞事件循环

在异步函数中使用 time.sleep(错误示范)

import asyncio
import time

async def bad_example():
    print("任务1开始")
    time.sleep(3)  # 危险!会阻塞整个事件循环
    print("任务1完成")

async def bad_example2():
    print("任务2开始")
    time.sleep(3)  # 危险!会阻塞整个事件循环
    print("任务2完成")

async def main():
    await asyncio.gather(bad_example(), bad_example2())

asyncio.run(main())

问题:虽然使用了 async/await,但 time.sleep(3) 会阻塞事件循环,导致:

  • 两个任务实际上串行执行
  • 其他协程无法运行
  • 失去了异步编程的优势

2. asyncio.sleep - 非阻塞式延迟

工作原理

import asyncio

async def async_task():
    print("开始执行")
    await asyncio.sleep(3)  # 暂停3秒,但不阻塞事件循环
    print("执行完成")

执行流程

事件循环(Event Loop)
┌──────────────────────────────────────────────┐
│                                              │
│  任务1: [运行] → [暂停3秒] → [完成]          │
│                    ↓                         │
│  任务2:           [运行] → [暂停3秒] → [完成]│
│                              ↓              │
│  任务3:                     [运行] → ...    │
│                                              │
└──────────────────────────────────────────────┘
     ↓ await 时释放控制权,允许其他任务运行 ↓

特点

  • ✅ 只暂停当前协程
  • 释放控制权给事件循环
  • ✅ 其他协程可以在暂停期间执行
  • ✅ 实现真正的并发执行

正确的异步使用

import asyncio

async def task1():
    print("任务1开始")
    await asyncio.sleep(3)  # 非阻塞暂停
    print("任务1完成")

async def task2():
    print("任务2开始")
    await asyncio.sleep(3)  # 非阻塞暂停
    print("任务2完成")

async def main():
    # 并发执行两个任务
    await asyncio.gather(task1(), task2())

asyncio.run(main())

输出

任务1开始
任务2开始
(等待3秒,两个任务同时暂停)
任务1完成
任务2完成

总耗时:约3秒(而非6秒),因为两个任务并发执行!


3. 实际对比测试

测试代码

import asyncio
import time
import threading

# ========== 使用 time.sleep ==========
def sync_task(name, delay):
    print(f"[{name}] 开始 - 线程: {threading.current_thread().ident}")
    time.sleep(delay)
    print(f"[{name}] 完成 - 耗时: {delay}秒")

def run_sync():
    print("\n=== 同步版本 (使用 time.sleep) ===")
    start = time.time()

    # 顺序执行
    sync_task("任务1", 2)
    sync_task("任务2", 2)
    sync_task("任务3", 2)

    print(f"总耗时: {time.time() - start:.2f}秒")

# ========== 使用 asyncio.sleep ==========
async def async_task(name, delay):
    print(f"[{name}] 开始 - 线程: {threading.current_thread().ident}")
    await asyncio.sleep(delay)
    print(f"[{name}] 完成 - 耗时: {delay}秒")

async def run_async():
    print("\n=== 异步版本 (使用 asyncio.sleep) ===")
    start = time.time()

    # 并发执行
    await asyncio.gather(
        async_task("任务1", 2),
        async_task("任务2", 2),
        async_task("任务3", 2)
    )

    print(f"总耗时: {time.time() - start:.2f}秒")

if __name__ == "__main__":
    run_sync()
    asyncio.run(run_async())

输出结果

=== 同步版本 (使用 time.sleep) ===
[任务1] 开始 - 线程: 12345
[任务1] 完成 - 耗时: 2秒
[任务2] 开始 - 线程: 12345
[任务2] 完成 - 耗时: 2秒
[任务3] 开始 - 线程: 12345
[任务3] 完成 - 耗时: 2秒
总耗时: 6.00秒

=== 异步版本 (使用 asyncio.sleep) ===
[任务1] 开始 - 线程: 12345
[任务2] 开始 - 线程: 12345
[任务3] 开始 - 线程: 12345
(等待2秒...)
[任务1] 完成 - 耗时: 2秒
[任务2] 完成 - 耗时: 2秒
[任务3] 完成 - 耗时: 2秒
总耗时: 2.00秒

性能对比

  • 同步版本:6秒(串行执行)
  • 异步版本:2秒(并发执行)
  • 性能提升:3倍!

4. FastAPI 中的实际应用

错误示例:在 async 路由中使用 time.sleep

from fastapi import FastAPI
import time
import asyncio

app = FastAPI()

@app.get("/bad")
async def bad_endpoint():
    # ❌ 错误!阻塞事件循环
    time.sleep(5)
    return {"message": "这会阻塞整个服务器5秒!"}

后果

  • 该路由执行期间,其他所有请求都会被阻塞
  • 服务器吞吐量急剧下降
  • 失去FastAPI的异步优势

正确示例:使用 asyncio.sleep

from fastapi import FastAPI
import asyncio

app = FastAPI()

@app.get("/good")
async def good_endpoint():
    # ✅ 正确!非阻塞暂停
    await asyncio.sleep(5)
    return {"message": "这不会阻塞其他请求"}

优势

  • 该路由暂停期间,其他请求可以正常处理
  • 服务器可以同时处理多个请求
  • 充分发挥FastAPI的异步性能

混合使用:同步路由用 time.sleep

@app.get("/sync-route")
def sync_route():
    # ✅ 在同步函数中使用 time.sleep 是合理的
    # FastAPI会在线程池中执行,不会阻塞事件循环
    time.sleep(5)
    return {"message": "在线程池中执行"}

5. 选择指南

何时使用 time.sleep

# ✅ 适用场景
def main():
    # 1. 普通同步脚本
    time.sleep(1)

    # 2. 多线程程序(每个线程独立)
    def worker():
        time.sleep(1)

    # 3. 同步路由(FastAPI会在线程池中执行)
    @app.get("/sync")
    def sync_route():
        time.sleep(1)
        return {"ok": True}

何时使用 asyncio.sleep

# ✅ 适用场景
async def main():
    # 1. 异步协程中
    await asyncio.sleep(1)

    # 2. 需要并发执行多个IO任务
    await asyncio.gather(
        asyncio.sleep(1),
        asyncio.sleep(2),
    )

    # 3. 异步路由
    @app.get("/async")
    async def async_route():
        await asyncio.sleep(1)
        return {"ok": True}

6. 常见错误

错误1:忘记 await

async def wrong():
    asyncio.sleep(3)  # ❌ 忘记 await,不会暂停!
    print("这会立即执行")

async def correct():
    await asyncio.sleep(3)  # ✅ 正确
    print("这会在3秒后执行")

错误2:在异步函数中混用 time.sleep

async def mixed():
    print("开始")
    await asyncio.sleep(1)  # ✅ 非阻塞
    time.sleep(1)           # ❌ 阻塞事件循环!
    await asyncio.sleep(1)  # ✅ 非阻塞
    print("完成")

错误3:在同步函数中尝试 await

def wrong():
    # ❌ 错误!同步函数不能使用 await
    await asyncio.sleep(1)

# 正确做法1:改用 async def
async def correct1():
    await asyncio.sleep(1)

# 正确做法2:使用 asyncio.run
def correct2():
    asyncio.run(asyncio.sleep(1))

7. 性能对比总结

串行执行 vs 并发执行

串行执行 (time.sleep):
任务1: [████████] 2秒
任务2:           [████████] 2秒
任务3:                     [████████] 2秒
总耗时: 6秒

并发执行 (asyncio.sleep):
任务1: [████████]
任务2: [████████]  同时执行
任务3: [████████]
总耗时: 2秒

适用场景对比

场景 推荐函数 原因
简单脚本延迟 time.sleep 简单直接
异步API开发 asyncio.sleep 不阻塞事件循环
同步API路由 time.sleep 在线程池执行,安全
异步IO密集任务 asyncio.sleep 高并发性能
CPU密集计算 多进程 不适用sleep

参考资源

posted @ 2026-03-03 18:18  shyNi  阅读(46)  评论(0)    收藏  举报