位置:首页 > Python > CentOS 上 Python 并发处理怎么做:线程、进程、线程池与 asyncio 选型说明

CentOS 上 Python 并发处理怎么做:线程、进程、线程池与 asyncio 选型说明

时间:2026-08-24  |  作者:极客少年  |  阅读:0

目录

  1. 先判断任务类型,再决定并发方案
  2. I/O 任务不多时,先看 threading
  3. CPU 密集型任务,更适合 multiprocessing
  4. 想少管细节,可以直接用 concurrent.futures
  5. 高并发 I/O 场景下,再考虑 asyncio
  6. CentOS 上做 Python 并发,实际可以这样选

前言

在 CentOS 上做 Python 并发,真正难的不是把任务“同时跑起来”,而是根据任务瓶颈选对模型。线程、进程、线程池和协程都能提高吞吐,但它们对应的场景、成本和限制完全不同;本文按任务类型拆解常见方案,并结合示例代码说明每种做法适合解决什么问题。

在 CentOS 上写 Python 并发程序,最常见的问题不是“怎么开并发”,而是“这类任务到底该用哪种并发模型”。线程、进程、线程池、协程都能把任务同时推进,但它们针对的瓶颈并不一样,选错之后不仅提速有限,甚至可能比单线程更慢。

这篇文章按实际选择路径来梳理常见方案:先区分 I/O 密集型和 CPU 密集型,再看 `threading`、`multiprocessing`、`concurrent.futures` 和 `asyncio` 各自适合什么场景、代码怎么写、限制在哪里。看完后,你至少能快速判断:当前任务该优先用线程、进程,还是直接上线程池、进程池或协程。

先判断任务类型,再决定并发方案

在 Python 里,并发方案的选择首先取决于任务瓶颈。

  • I/O 密集型任务:大部分时间花在等待网络、磁盘、数据库响应上,例如网络请求、文件读写。
  • CPU 密集型任务:主要时间耗在计算上,例如图像处理、数值计算。

如果是 I/O 密集型任务,通常优先考虑 threadingThreadPoolExecutorasyncio。如果是 CPU 密集型任务,则更适合 multiprocessingProcessPoolExecutor,因为它们能绕过 GIL(全局解释器锁)带来的限制。

I/O 任务不多时,先看 threading

threading 是 Python 自带的多线程方案,适合网络请求、文件读写这类 I/O 密集型任务。它的优点是上手快,写法直接,适合并发量不大、逻辑也比较简单的场景。

import threading

def worker(num):
    """线程任务函数"""
    print(f"Worker: {num}")

threads = []
for i in range(5):
    t = threading.Thread(target=worker, args=(i,))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

这段代码会创建 5 个线程,每个线程执行一次 worker(),最后通过 join() 等待所有线程结束。

它适合什么场景

如果你的程序主要是在“等”,而不是在“算”,多线程通常能把空闲等待时间利用起来。例如同时发起多个网络请求,或者同时处理多个文件读写任务。

需要注意什么

多线程并不等于适合所有任务。由于 Python 的 GIL 存在,threading 在 CPU 密集型任务上的表现通常不理想,所以不要把它当成通用加速工具,更不适合拿去做大量纯计算。

CPU 密集型任务,更适合 multiprocessing

当任务主要消耗 CPU 时,multiprocessing 往往比多线程更合适。原因在于它采用多进程模型,每个进程都有独立的 Python 解释器,可以真正利用多核 CPU 并行执行。

import multiprocessing

def worker(num):
    """进程任务函数"""
    print(f"Worker: {num}")

processes = []
for i in range(5):
    p = multiprocessing.Process(target=worker, args=(i,))
    processes.append(p)
    p.start()

for p in processes:
    p.join()

这段代码同样启动 5 个执行单元,但这次是 5 个独立进程,而不是 5 个线程。

它为什么能绕过 GIL

GIL 会限制同一时刻只有一个线程执行 Python 字节码,但它不会跨进程生效。也就是说,多进程方案可以把计算任务分摊到多个 CPU 核心上,这也是它更适合图像处理、数值计算等场景的原因。

Python 并发方案选择流程与任务类型对应关系图
Python 并发方案怎么选先区分 I/O 密集型和 CPU 密集型,再映射到线程、进程、线程池或协程。

它的代价是什么

进程的创建、销毁以及进程间通信开销都比线程更高。因此,如果任务本身很轻,或者本来就是 I/O 等待为主,多进程未必划算。

想少管细节,可以直接用 concurrent.futures

如果你不想手动管理线程和进程的创建、回收,concurrent.futures 是更省心的选择。它提供了线程池和进程池的统一接口,适合需要限制并发数量、批量提交任务的场景。

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

def worker(num):
    """任务函数"""
    print(f"Worker: {num}")

# 使用线程池
with ThreadPoolExecutor(max_workers=5) as executor:
    for i in range(5):
        executor.submit(worker, i)

# 使用进程池
with ProcessPoolExecutor(max_workers=5) as executor:
    for i in range(5):
        executor.submit(worker, i)

相比直接操作 threadingmultiprocessing,线程池和进程池的好处在于接口统一,代码更短,也更容易控制并发上限。

什么时候优先选它

当你已经明确任务类型,但又不想自己维护线程列表、进程列表时,线程池和进程池通常是更实用的默认选项。尤其是在服务端脚本、批处理任务里,这种写法更容易维护。

高并发 I/O 场景下,再考虑 asyncio

asyncio 也是面向 I/O 密集型任务的,但它的思路和多线程不同。它通过协程(coroutine)在单线程内完成异步并发,不依赖多线程或多进程,运行开销通常更低,特别适合高并发网络编程。

threading、multiprocessing、asyncio 三种并发方式的适用范围与限制对比图
线程、进程与协程的差别线程、多进程和协程都能并发执行任务,但适用瓶颈、开销和限制完全不同,不能混着理解。
import asyncio

async def worker(num):
    """异步任务函数"""
    print(f"Worker: {num}")
    await asyncio.sleep(1)

async def main():
    tasks = [worker(i) for i in range(5)]
    await asyncio.gather(*tasks)

asyncio.run(main())

这里的 await asyncio.sleep(1) 用来模拟 I/O 等待,比如等待数据库查询或网络响应。多个任务会在等待期间交出执行权,让事件循环继续推进其他任务。

它适合什么类型的程序

如果你面对的是大量网络连接、海量请求或需要维护很多并发 I/O 会话的程序,asyncio 往往比传统线程方案更轻量。

它的边界也很明确

asyncio 只能很好地处理 I/O 密集型任务。一旦协程内部塞进大量 CPU 计算,就会阻塞整个事件循环,导致整体并发能力下降。因此,它并不是 CPU 任务的替代方案。

CentOS 上做 Python 并发,实际可以这样选

如果只看落地选择,可以按下面这个判断思路来:

  • CPU 密集型任务:首选 multiprocessingProcessPoolExecutor
  • I/O 密集型任务,且任务量不大:可用 threadingThreadPoolExecutor
  • I/O 密集型任务,且并发量很高:例如上千个网络连接,更适合 asyncio
  • 想兼顾易用性和控制力:优先考虑 concurrent.futures 的线程池或进程池

没有哪一种方案能覆盖所有情况。真正影响性能的,不是“用了并发”这件事本身,而是并发模型是否和任务瓶颈匹配。先分清自己是在等 I/O,还是在吃 CPU,再选工具,通常就不会走偏。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多