Python 多线程 threading + 多进程 multiprocessing 完整实操教程

文章目录

  • [第一部分:多线程 threading 使用教程](#第一部分:多线程 threading 使用教程)
  • [第二部分:多进程 multiprocessing 使用教程](#第二部分:多进程 multiprocessing 使用教程)
    • 核心特点
    • [1. 基础创建进程](#1. 基础创建进程)
    • [2. 进程间数据通信](#2. 进程间数据通信)
    • [3. 进程池(CPU密集批量计算首选)](#3. 进程池(CPU密集批量计算首选))
  • 第三部分:多线程与多进程场景选择标准
    • [选用多线程 threading / ThreadPoolExecutor](#选用多线程 threading / ThreadPoolExecutor)
    • [选用多进程 multiprocessing / ProcessPoolExecutor](#选用多进程 multiprocessing / ProcessPoolExecutor)

Python 实现并发两大标准库:

  1. threading:多线程,适合IO密集(爬虫、文件读写、接口请求),轻量、共享内存,受GIL限制无法多核计算;
  2. multiprocessing:多进程,适合CPU密集(数值运算、图像处理、批量加密),独立内存,绕过GIL实现多核并行。

下文全部为可直接运行的完整示例,分模块讲解基础用法、数据通信、线程池/进程池实战,无冗余理论,侧重工程使用。

第一部分:多线程 threading 使用教程

1. 基础创建线程两种方式

方式1:函数式创建(日常开发最常用)

核心:threading.Thread(target=执行函数, args=参数元组)

  • start():启动线程
  • join():主线程阻塞等待子线程完成
python 复制代码
import threading
import time

def task(name, delay):
    print(f"线程 {name} 开始执行")
    time.sleep(delay)  # 模拟IO阻塞
    print(f"线程 {name} 执行完毕")

if __name__ == "__main__":
    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("所有子线程运行完成")

方式2:继承Thread类自定义线程(复杂业务封装)

重写run()方法,线程启动后自动执行run内逻辑

python 复制代码
import threading
import time

class MyThread(threading.Thread):
    def __init__(self, name, delay):
        super().__init__()
        self.name = name
        self.delay = delay

    def run(self):
        print(f"自定义线程 {self.name} 启动")
        time.sleep(self.delay)
        print(f"自定义线程 {self.name} 结束")

if __name__ == "__main__":
    t1 = MyThread("线程1", 2)
    t2 = MyThread("线程2", 1)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("自定义线程全部执行完毕")

2. 共享变量加锁解决数据错乱

多线程共享全局变量会产生竞态条件,使用threading.Lock互斥锁保证同一时间仅一个线程修改共享数据

python 复制代码
import threading

count = 0
lock = threading.Lock()

def add_count():
    global count
    for _ in range(100000):
        # with自动上锁、释放锁,无需手动release,避免死锁
        with lock:
            count += 1

if __name__ == "__main__":
    thread_list = []
    for i in range(5):
        t = threading.Thread(target=add_count)
        thread_list.append(t)
        t.start()
    # 等待全部线程执行完成
    for t in thread_list:
        t.join()
    print("最终统计值:", count)

3. 线程安全通信:queue队列

不推荐直接全局变量传参,queue.Queue内置锁,生产者消费者标准方案

python 复制代码
import threading
import queue
import time

q = queue.Queue(maxsize=10)

# 生产者:写入数据
def producer():
    for i in range(5):
        q.put(f"任务{i}")
        print(f"生产:任务{i}")
        time.sleep(0.2)

# 消费者:读取数据
def consumer():
    while True:
        data = q.get()
        print(f"消费:{data}")
        q.task_done()
        time.sleep(0.3)

if __name__ == "__main__":
    t_pro = threading.Thread(target=producer)
    t_con = threading.Thread(target=consumer, daemon=True)
    t_pro.start()
    t_con.start()
    t_pro.join()
    q.join()
    print("所有数据消费完成")

4. 线程池(推荐大量并发场景)

手动创建大量线程开销大,concurrent.futures.ThreadPoolExecutor自动管理线程数量

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

def spider(url):
    print(f"正在请求:{url}")
    time.sleep(1)
    return f"{url} 请求完成"

if __name__ == "__main__":
    url_list = ["baidu", "bing", "qq", "douyin"]
    # 最大并发线程4个
    with ThreadPoolExecutor(max_workers=4) as executor:
        # 批量提交任务
        results = executor.map(spider, url_list)
    # 遍历结果
    for res in results:
        print(res)

第二部分:多进程 multiprocessing 使用教程

核心特点

  1. 每个进程拥有独立内存空间,默认不共享变量;
  2. 绕过GIL,多核CPU并行计算;
  3. 创建开销大于线程,通信需要专用工具(Queue、Pipe、Manager)。

1. 基础创建进程

用法和threading高度相似,multiprocessing.Process

python 复制代码
import multiprocessing
import time

def calc_task(num):
    print(f"进程 {num} 开始计算")
    # 模拟CPU密集运算
    res = sum(i for i in range(10000000))
    print(f"进程 {num} 计算完成,结果:{res % 1000}")

if __name__ == "__main__":
    # Windows系统必须写if __name__ == "__main__",否则无限递归创建进程
    p1 = multiprocessing.Process(target=calc_task, args=(1,))
    p2 = multiprocessing.Process(target=calc_task, args=(2,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print("所有进程计算结束")

2. 进程间数据通信

进程内存隔离,普通全局变量无法互通,两种常用通信方式:

方式1:multiprocessing.Queue 队列(多进程安全)

python 复制代码
import multiprocessing

def producer(q):
    for i in range(3):
        q.put(f"数据{i}")

def consumer(q):
    while not q.empty():
        data = q.get()
        print("进程读取:", data)

if __name__ == "__main__":
    q = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=producer, args=(q,))
    p2 = multiprocessing.Process(target=consumer, args=(q,))
    p1.start()
    p1.join()
    p2.start()
    p2.join()

方式2:Manager共享变量(多进程共享数值、列表)

python 复制代码
import multiprocessing

def add_num(share_num, lock):
    for _ in range(10000):
        with lock:
            share_num.value += 1

if __name__ == "__main__":
    # 创建进程管理器
    manager = multiprocessing.Manager()
    share_count = manager.Value("i", 0)  # 共享整型变量
    lock = manager.Lock()
    p_list = []
    for i in range(4):
        p = multiprocessing.Process(target=add_num, args=(share_count, lock))
        p_list.append(p)
        p.start()
    for p in p_list:
        p.join()
    print("多进程共享数值:", share_count.value)

3. 进程池(CPU密集批量计算首选)

ProcessPoolExecutor自动管理进程数量,充分利用多核

python 复制代码
from concurrent.futures import ProcessPoolExecutor

def heavy_calc(n):
    total = 0
    for i in range(n):
        total += i ** 2
    return total

if __name__ == "__main__":
    task_nums = [200000, 300000, 400000, 500000]
    # 进程数默认等于CPU核心数
    with ProcessPoolExecutor() as executor:
        res = executor.map(heavy_calc, task_nums)
    for r in res:
        print("计算结果:", r)

第三部分:多线程与多进程场景选择标准

选用多线程 threading / ThreadPoolExecutor

  1. IO密集型任务:网络爬虫、HTTP接口请求、文件读写、数据库查询;
  2. 任务阻塞时间远大于计算时间,GIL会在IO等待时释放,并发提升明显;
  3. 需要轻量并发,资源占用低,大量任务也不会消耗过多内存。

选用多进程 multiprocessing / ProcessPoolExecutor

  1. CPU密集型任务:大数据循环计算、图片批量处理、视频解码、加密算法;
  2. 需要利用多核CPU,规避GIL限制,实现真正并行加速;
  3. 任务崩溃隔离,单个进程异常不会导致整个程序退出。
相关推荐
许彰午1 小时前
24_Java NIO核心组件
java·python·nio
不会C语言的男孩1 小时前
C++ Primer 第18章:用于大型程序的工具
开发语言·c++
星恒随风1 小时前
C++ 类和对象入门(三):拷贝构造、赋值运算符重载和深浅拷贝
开发语言·c++·笔记·学习
RickyWasYoung1 小时前
【Matlab】科研绘图配色-极简版
开发语言·matlab
凡人叶枫1 小时前
Effective C++ 条款03:尽可能使用 const
linux·开发语言·c++·嵌入式开发
lie..1 小时前
基于大模型的智能客服系统部署与使用(二):接入前端可视化界面
人工智能·python
光影6272 小时前
Python接口自动化测试----Requests库基础入门
开发语言·python·测试工具·pycharm·自动化
程序媛_2 小时前
【Python】连接PostgreSQL获取手机验证码
开发语言·python·postgresql
ch.ju2 小时前
Java Programming Chapter 4——Inherited call
java·开发语言