Python多线程入门:从零到能用

为什么需要多线程?

单线程程序一次只能做一件事。如果你的程序里有网络请求、文件IO、数据库查询这类"等结果"的操作,CPU其实在空转。

多线程的核心目的:让CPU在等待的时候,去干别的事。


先搞懂两个概念

概念 说明
进程 独立的程序,内存隔离,开销大
线程 进程内部的执行单元,共享内存,开销小
GIL Python的全局解释器锁,同一时刻只有一个线程在执行Python代码

⚠️ 关键结论:Python多线程适合IO密集型任务,不适合CPU密集型任务。

  • ✅ 网络请求、文件读写、数据库查询 → 多线程有用
  • ❌ 纯计算、图像处理 → 多线程没用(GIL限制),用多进程

最基础的用法

python 复制代码
import threading
import time

def task(name, delay):
    print(f"{name} 开始")
    time.sleep(delay)
    print(f"{name} 结束")

# 创建线程
t1 = threading.Thread(target=task, args=("任务A", 2))
t2 = threading.Thread(target=task, args=("任务B", 1))

# 启动线程
t1.start()
t2.start()

# 等待线程结束
t1.join()
t2.join()

print("全部完成")

输出:

复制代码
任务A 开始
任务B 开始
任务B 结束
任务A 结束
全部完成

两个任务同时在跑,总耗时约2秒,而不是3秒。


实战:并发请求接口

这是最常见的使用场景:

python 复制代码
import threading
import requests

urls = [
    "https://api.example.com/1",
    "https://api.example.com/2",
    "https://api.example.com/3",
]

results = []
lock = threading.Lock()  # 保护共享数据

def fetch(url):
    resp = requests.get(url, timeout=5)
    with lock:  # 加锁,避免多个线程同时写列表
        results.append(resp.status_code)

threads = []
for url in urls:
    t = threading.Thread(target=fetch, args=(url,))
    t.start()
    threads.append(t)

for t in threads:
    t.join()

print(f"完成 {len(results)} 个请求")

进阶:用 ThreadPoolExecutor(推荐)

手动管理线程太麻烦,直接用线程池:

python 复制代码
from concurrent.futures import ThreadPoolExecutor
import requests

urls = ["url1", "url2", "url3", ...]

def fetch(url):
    return requests.get(url).status_code

with ThreadPoolExecutor(max_workers=5) as executor:
    results = list(executor.map(fetch, urls))

print(results)

✅ 自动管理线程数量,不用手动 start/join

✅ max_workers 控制并发数,避免把对方服务器打挂


三个常见坑

坑 说明 解决方案
GIL导致多线程不加速计算 for i in range(10000000): pass 开10个线程也不会变快 CPU密集型用 multiprocessing
共享数据竞争 多个线程同时改同一个变量,结果不可预期 用 threading.Lock() 加锁
线程数开太多 每个线程有开销,开1000个线程反而更慢 IO密集型:线程数 = CPU核数 × 2~5

什么时候用多线程?一张表说清

场景 推荐方案
请求多个API ✅ ThreadPoolExecutor
读写多个文件 ✅ 多线程
爬虫 ✅ 多线程
大量数学计算 ❌ 用 multiprocessing
简单脚本,任务少 ❌ 没必要,单线程就够

一句话总结

Python多线程 = 让IO等待的时间不被浪费。记住GIL的存在,别用它做计算,它就很好用。

相关推荐
apcipot_rain3 小时前
C++转Java日记(04)
java·开发语言·c++
特立独行的猫A3 小时前
我给女儿写了个打字练习:一边敲键盘,一边把小学英语单词记牢
java·后端·python
cpolar技术支持3 小时前
「我这边连不上你那个服务」—— 用清单驱动的 TCP 连通性只读看板,cpolar 让远端同事自己取证
python·内网穿透·tcp·cpolar·网络诊断
云和数据.ChenGuang4 小时前
LangGraph 异步 Node 的设计与写法实践
开发语言·人工智能·python·机器学习·php
天诰5 小时前
SA-K-11 检索会消失吗与四个未解问题
java·服务器·人工智能·python·机器学习·ai编程
benchmark_cc6 小时前
用 QuantDash 读取美股行情:AAPL.US 的运行前检查、排错顺序与数据校验清单
python·数据分析·pandas·量化交易·股票数据·quantdash
蜗牛一步步往上爬7 小时前
第十六章 C++语言在深度学习中的应用
开发语言·c++·深度学习
羲云网络9 小时前
GPT Image 2.6 接入指南:Flare、Sunburst 怎么选,编辑失败如何排查
人工智能·python·aigc·图像生成·acedatacloud
张张123y9 小时前
DSH 插件调试避坑:client.js 设置面板、热重载与高频报错排查表
开发语言·javascript·人工智能·开源·ecmascript·后端开发·ai agent
冻柠檬飞冰走茶12 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划