提示:本网站现在为维护调试状态

Python 並行処理:asyncio vs ThreadPool vs ProcessPool

Choyeon
Choyeon
2026年9月5日 1 分で読了 662 閲覧
365 字 2,249 文字 更新日 2026年11月8日
Python 並行処理:asyncio vs ThreadPool vs ProcessPool
目次

Python Concurrency: asyncio vs ThreadPool vs ProcessPool

The GIL makes Python concurrency confusing. IO-bound and CPU-bound workloads demand different models - pick wrong and performance worsens.

Three Models and Code

ThreadPool submits blocking calls; GIL releases on IO waits (10-50 workers). ProcessPool uses subprocesses to evade GIL for CPU work (serialization overhead). asyncio schedules coroutines on one thread for massive light IO concurrency.

import asyncio, time, requests, httpx
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed
from typing import List

URLS = [f"https://jsonplaceholder.typicode.com/posts/{i}" for i in range(1, 51)]

def fetch_sync(url: str) -> dict:
    return requests.get(url, timeout=10).json()

async def fetch_async(client, url: str) -> dict:
    r = await client.get(url, timeout=10.0)
    return r.json()

def run_threadpool(urls, maxw=20):
    t0 = time.perf_counter()
    with ThreadPoolExecutor(max_workers=maxw) as ex:
        fs = [ex.submit(fetch_sync, u) for u in urls]
        results = [f.result() for f in as_completed(fs)]
    print(f"[ThreadPool] {len(results)} tasks, {time.perf_counter()-t0:.2f}s")

def cpu_heavy(n):
    sieve = [True]*(n+1); sieve[0]=sieve[1]=False
    for i in range(2, int(n**0.5)+1):
        if sieve[i]: sieve[i*i::i] = [False]*len(sieve[i*i::i])
    return sum(sieve)

def run_processpool(args):
    t0 = time.perf_counter()
    with ProcessPoolExecutor() as ex:
        results = list(ex.map(cpu_heavy, args))
    print(f"[ProcessPool] sum={sum(results)}, {time.perf_counter()-t0:.2f}s")

async def run_asyncio(urls):
    t0 = time.perf_counter()
    async with httpx.AsyncClient() as client:
        tasks = [fetch_async(client, u) for u in urls]
        results = await asyncio.gather(*tasks)
    print(f"[asyncio] {len(results)} tasks, {time.perf_counter()-t0:.2f}s")

if __name__ == "__main__":
    run_threadpool(URLS)
    run_processpool([100000]*8)
    asyncio.run(run_asyncio(URLS))

Decision Framework and Benchmarks

Pure CPU math → ProcessPool. Network/file IO → asyncio or ThreadPool. Mixed → asyncio.run_in_executor offloads CPU to pool while IO stays in coroutines.

Dimension ThreadPool ProcessPool asyncio
Principle Multi-thread shared GIL Multi-process, own GIL Single-thread loop + coroutines
GIL impact Released on IO / useless on CPU No GIL at all No contention
50 HTTP reqs ~5-8s ~40s (fork slow) ~1.5-3s
8 CPU primes ~45s (serial) ~7s (multi-core) ~40s (single)
Max concurrency Hundreds Cores × 2 Thousands+
Migration cost Low Medium (pickle) High (full async chain)

Best Practices

Prefer asyncio for IO first; fall to ThreadPool if dependencies synchronous. Use ProcessPool for CPU tasks and cap workers at 1-2 × core count.

X微博Telegram

筆者について

投票

你最希望 Rosetta 优先加入哪项功能?

社区投票(演示数据,可后台删除)

コメント (7)

0 / 3000
技术笔记控
技术笔记控tech-notes.fun2026年9月3日

受益匪浅,感谢大佬分享!

摸鱼达人小王
摸鱼达人小王2026年9月2日

请问一下,文中提到的连接池配置,如果是在高并发场景下,一般设置多少比较合适?

嵌入式极客
嵌入式极客embedded-lab.io2026年9月2日

代码示例里那个 SQL 查询是不是应该加个 LIMIT?不然数据量大的时候全表扫描会很慢哦。

产品汪本汪
产品汪本汪pmdiary.io2026年9月2日

有个小问题:你文中用的是 @Async 注解,这个默认用的是 SimpleAsyncTaskExecutor,生产环境是不是最好手动配一个线程池?

游戏策划阿哲
游戏策划阿哲2026年9月1日

楼主,我按照你的步骤操作后启动报错:Error creating bean with name 'dataSource',版本是 Spring Boot 3.2,请问有遇到过吗?

奶茶味程序媛
奶茶味程序媛2026年9月1日

建议加一下关于幂等性的讨论,现在的分布式系统里这个真的太重要了,很多坑都是没处理好幂等导致的。

DevOps小能手
DevOps小能手devops-lab.cn2026年9月1日

作为一个刚入行的后端新人,这篇文章帮我理清了好多概念,谢谢博主持续输出高质量内容!

関連記事

アルゴリズム:動的計画法 5大テンプレート

アルゴリズム:動的計画法 5大テンプレート

DP完全制覇:5ステップ共通フレームワーク+5大高頻度テンプレート:ナップサック、部分列、区間DP、ビットDP、木DPに典型コードと変形ポイント。

1 分で読了
FastAPI クイックスタート - 高性能 REST API の構築

FastAPI クイックスタート - 高性能 REST API の構築

FastAPI は現代の Python Web フレームワークの中でも傑出しており、型ヒントによる自動ドキュメント生成、非同期サポート、Node.js 並みのパフォーマンスを提供します。この実践ガイドでは、ルート定義、リクエスト検証、依存性注入、データベース統合を含む完全な CRUD API をゼロから構築します。

この記事は閲覧パスワードが必要です 4 分で読了
RAG 検索拡張生成実践:Embedding + Vector DB + ReRank

RAG 検索拡張生成実践:Embedding + Vector DB + ReRank

プロダクション級RAGをゼロから構築:文書チャンク戦略、Embeddingモデル選定、Vector DBフィルタ検索、RerankerによるTop-K精緻化、引用根拠とプロンプト圧縮。完全動作コード付き。

1 分で読了
Alembic ディープガイド:DBマイグレーション + 自動生成 + ブランチマージ

Alembic ディープガイド:DBマイグレーション + 自動生成 + ブランチマージ

SQLAlchemy公式マイグレーションツール Alembic 完全ガイド:env.py設定、autogenerateによるモデル変更検出(カラム・インデックス・制約)、バッチスクリプト、ダウングレードロールバック戦略、複数人開発時のマイグレーションコンフリクトとhead分岐マージの標準SOP、本番デプロイチェックリスト付き。

1 分で読了
Nuxt 3 応用 - SSR と SSG の深堀り解説

Nuxt 3 応用 - SSR と SSG の深堀り解説

Nuxt 3 は Vue 3 と Vite 上に構築され、新しいレンダリングエンジン Nitro を導入しました。この記事では、サーバーサイドレンダリング(SSR)、静的サイト生成(SSG)、インクリメンタル静的再生成(ISR)の3つのコアモードの動作原理、ユースケース、パフォーマンスの違いを深堀りします。

1 分で読了
Redis キャッシュ設計パターン

Redis キャッシュ設計パターン

3種のキャッシュパターン:Cache-Aside、Write-Through、Write-Behindの実装と適用シーン、キャッシュ問題対策まで。

1 分で読了