Khi cần chạy blocking code hoặc CPU-bound tasks trong async context:
python
import asyncio
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
# ThreadPoolExecutor — cho blocking I/O trong sync libraries
executor = ThreadPoolExecutor(max_workers=10)
async def call_blocking_lib():
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(
executor,
blocking_function, # Không thể await được
arg1, arg2
)
return result
# ProcessPoolExecutor — cho CPU-bound tasks
cpu_executor = ProcessPoolExecutor(max_workers=4)
def heavy_computation(data): # Pure CPU work
return [x**2 for x in data]
async def process_data(large_list):
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(
cpu_executor,
heavy_computation,
large_list
)
return result
# asyncio.to_thread (Python 3.9+) — shortcut cho ThreadPool
async def modern_approach():
result = await asyncio.to_thread(blocking_function, arg)Pitfall: Objects truyền qua ProcessPoolExecutor phải pickle-able.
ThreadPoolExecutor shares memory nhưng bị GIL với CPU-bound tasks.