同步 vs 异步
同步编程:代码按顺序执行,遇到I/O操作时等待。
import time
def fetch_data(url):
time.sleep(2) # 阻塞2秒
return f"数据来自 {url}"
# 3个请求需要6秒
异步编程:遇到I/O操作时不阻塞,去执行其他任务。
import asyncio
async def fetch_data(url):
await asyncio.sleep(2) # 非阻塞
return f"数据来自 {url}"
async def main():
tasks = [fetch_data(f"https://api{i}.com") for i in range(3)]
results = await asyncio.gather(*tasks)
# 3个请求只需2秒!
asyncio.run(main())
核心概念
| 概念 | 说明 |
|---|---|
| event loop | 事件循环,异步程序的大脑 |
| coroutine | 协程,异步函数 |
| await | 等待异步操作完成 |
| Task | 对协程的封装 |
实战:异步HTTP请求
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def fetch_all(urls):
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
return await asyncio.gather(*tasks)
实战:异步爬虫
class AsyncCrawler:
def __init__(self, max_concurrent=10):
self.semaphore = asyncio.Semaphore(max_concurrent)
async def crawl(self, start_url, max_pages=50):
async with aiohttp.ClientSession() as session:
queue = asyncio.Queue()
await queue.put(start_url)
while not queue.empty():
url = await queue.get()
html = await self.fetch(session, url)
links = self.parse_links(html)
for link in links:
await queue.put(link)
常见陷阱
- 不要在异步函数中调用同步阻塞代码(如time.sleep、requests.get)
- 不要忘记await协程调用
- 使用Semaphore控制并发数,避免资源耗尽
性能对比
| 场景 | 同步耗时 | 异步耗时 | 提升 |
|---|---|---|---|
| 100个HTTP请求 | 200秒 | 2.5秒 | 80x |
| 1000个数据库查询 | 500秒 | 8秒 | 62x |
📢 本文为精简版,完整版包含独家工具推荐和深度分析,请访问 WD Tech Blog 查看!
关注我的博客获取最新科技资讯、AI教程和效率工具推荐!
Top comments (0)