Python Threading 串行VS并发

Threading 串行VS并发

IO 密集型

结果

>>> 串行开始...
下载https://www.baidu.com/成功,状态码为200
下载https://www.sina.com.cn/成功,状态码为200
下载https://www.bilibili.com/成功,状态码为412
耗时:0.42061281204223633
>>> 串行结束...
>>> 并发开始...
下载https://www.baidu.com/成功,状态码为200
下载https://www.sina.com.cn/成功,状态码为200
下载https://www.bilibili.com/成功,状态码为412
耗时:0.1446540355682373
>>> 并发结束...

示例代码

# -*- coding: utf-8 -*-
# I/O密集时多线程例子:一边打印一边下载网页内容 串行VS并发
import requests
import threading
import time

# 用几个响应速度较快的真实网页
urls = [
    "https://www.baidu.com/",
    "https://www.sina.com.cn/",
    "https://www.bilibili.com/"
]


def download(url):
    try:
        r = requests.get(url, timeout=3)
        print(f"下载{url}成功,状态码为{r.status_code}")
    except requests.RequestException as e:
        print(e)


# ===== 串行
def run_serial():
    print(">>> 串行开始...")
    start_time = time.time()
    for url in urls:
        download(url)
    end_time = time.time()
    print(f"耗时:{end_time - start_time}")
    print(">>> 串行结束...")


# ==== 并发(多线程)
def run_threading():
    print(">>> 并发开始...")
    start_time = time.time()
    threads = []
    for url in urls:
        t = threading.Thread(target=download, args=(url,))  # target=函数名,args=函数参数(元组)
        threads.append(t)
        t.start()  # 线程开始执行

    for t in threads:
        t.join()  # join 主线程等待子线程执行完
    end_time = time.time()
    print(f"耗时:{end_time - start_time}")
    print(">>> 并发结束...")


if __name__ == '__main__':
    run_serial()
    run_threading()

计算密集型

结果

CPU密集任务运行时,并行并不会比串行快多少,达不到加速的效果

>>> 开始串行...
>>> 串行耗时: 73.33004999160767 秒
>>> 开始并发...
>>> 并发耗时: 73.11574292182922 秒

示例代码

# -*- coding: utf-8 -*-
import math

import requests
import threading
import time

# “烧 CPU”的函数:对一大批数字做平方根运算(math.sqrt())

N = 500000000


def cpu_task():
    total = 0
    for i in range(N):
        total += math.sqrt(i)
    return total


# ==== 串行
def run_serial():
    print(">>> 开始串行...")
    start_time = time.time()
    cpu_task()
    cpu_task()
    cpu_task()
    print(">>> 串行耗时:", time.time() - start_time, "秒")


# ==== 并发
def run_threaded():
    print(">>> 开始并发...")
    start_time = time.time()
    threas = []
    for _ in range(3):
        t = threading.Thread(target=cpu_task)
        t.start()
        threas.append(t)
    for t in threas:
        t.join()
    print(">>> 并发耗时:", time.time() - start_time, "秒")


if __name__ == '__main__':
    run_serial()
    run_threaded()

总结:多线程的优势与局限

I/O 密集 请求网页、读写文件、等待数据库 ✅ 非常适合
CPU 密集 图像处理、大量计算、加密解密 ❌ 会被 GIL 限制,不如用多进程
少量任务 任务不多,时间也短 ⚠️ 线程切换反而是开销
并发数量极大 上千并发、强隔离 ⚠️ 推荐协程/进程池,线程管理成本高

参考来源

https://zhuanlan.zhihu.com/p/1923003098605033459

posted @ 2025-09-22 13:41  染指未来  阅读(9)  评论(0)    收藏  举报