🎯 本節目標
- 理解多線程/多進程/協程的應用場景
- 掌握threading與multiprocessing核心用法
- 學會使用asyncio進行異步編程
- 開發實戰項目:高并發爬蟲引擎
- 破解GIL鎖的性能迷思
1?? 并發編程三劍客
🎻 生活化比喻:
- 多線程 → 餐廳多個服務員共享廚房
- 進程 → 連鎖餐廳各自獨立分店
- 協程 → 一個服務員同時處理多桌點餐
2?? 多線程實戰:閃電下載器
import threading
import requests def download(url, filename): print(f"🚀 開始下載 {filename}") data = requests.get(url).content with open(filename, 'wb') as f: f.write(data) print(f"? {filename} 下載完成") # 創建線程列表
threads = []
urls = [ ('https://example.com/1.jpg', 'pic1.jpg'), ('https://example.com/2.mp4', 'video.mp4')
] for url, name in urls: t = threading.Thread(target=download, args=(url, name)) threads.append(t) t.start() # 等待所有線程完成
for t in threads: t.join()
print("🎉 所有下載任務完成!")
3?? 協程魔法:異步爬蟲引擎
import asyncio
import aiohttp async def async_fetch(session, url): async with session.get(url) as response: return await response.text() async def main(): async with aiohttp.ClientSession() as session: tasks = [ async_fetch(session, f"https://api.example.com/data/{i}") for i in range(100) ] results = await asyncio.gather(*tasks) print(f"📊 獲取到 {len(results)} 條數據") # Python 3.7+ 使用 asyncio.run()
asyncio.run(main())
4?? GIL鎖:性能瓶頸與突破
🔒 GIL(全局解釋器鎖)真相
- 單進程中同一時間只有一個線程執行字節碼
- 單進程中同一時間只有一個線程執行字節碼
破解方案:
# 使用多進程繞過GIL限制
from multiprocessing import Pool def heavy_compute(n): return sum(i*i for i in range(n)) with Pool(4) as p: results = p.map(heavy_compute, [10**6]*4)
5?? 實戰項目:智能并發爬蟲
import concurrent.futures
import requests def advanced_crawler(urls, max_workers=5): """智能并發爬蟲""" with concurrent.futures.ThreadPoolExecutor(max_workers) as executor: future_to_url = { executor.submit(requests.get, url): url for url in urls } for future in concurrent.futures.as_completed(future_to_url): url = future_to_url[future] try: data = future.result() print(f"🌐 {url} 抓取成功(長度:{len(data.text)})") except Exception as e: print(f"? {url} 抓取失敗:{str(e)}") # 使用示例
url_list = [f"https://example.com/page/{i}" for i in range(50)]
advanced_crawler(url_list, max_workers=10)
📚 知識圖譜
并發編程決策樹:┌───────────────┐ │ 任務類型? │ └───────┬───────┘ ┌────────────┴────────────┐ ┌─────▼─────┐ ┌──────▼──────┐ │ I/O密集型 │ │ CPU密集型 │ └─────┬─────┘ └──────┬──────┘ ┌──────▼──────┐ ┌──────▼──────┐ │ 多線程/協程 │ │ 多進程 │ └─────────────┘ └─────────────┘ PyCharm并發調試技巧: 1. 線程/進程ID顯示:View → Toolbar → Show Threads 2. 協程堆棧追蹤:async堆棧模式切換 3. 內存/CPU監控:右鍵狀態欄 → 勾選Memory Indicator
🛠? 課后挑戰
- 使用生產者-消費者模式實現多線程任務隊列
- 將異步爬蟲改造為支持斷點續傳
- 用多進程計算100個1e6大小隨機數組的標準差
💡 參考答案提示:
# 生產者-消費者模型核心
import queue task_queue = queue.Queue(maxsize=100) def producer(): while True: item = generate_item() task_queue.put(item) def consumer(): while True: item = task_queue.get() process_item(item) task_queue.task_done()
🚀 下節劇透:《網絡編程:連接世界的數字橋梁
👉 你將解鎖:
- TCP/UDP協議底層原理
- Socket編程實戰技巧
- HTTP服務器從零實現
- 實戰:即時聊天系統開發