面试题答案
一键面试设计思路
- 异步I/O操作:使用
asyncio
库来处理异步I/O任务,因为asyncio
基于事件循环,在I/O操作时可以释放线程,让其他任务得以执行,适合处理如网络请求、文件I/O等I/O密集型任务。 - CPU密集型任务:
ThreadPoolExecutor
是concurrent.futures
模块中的类,它通过线程池来管理线程,对于CPU密集型任务,虽然Python由于GIL(全局解释器锁)的存在无法利用多核优势,但线程池可以在一定程度上并发执行多个任务,避免阻塞主线程。 - 协调两者:将CPU密集型任务提交到
ThreadPoolExecutor
线程池中执行,然后在asyncio
的事件循环中通过run_in_executor
方法来调用线程池中的任务,这样可以将CPU密集型任务融入到异步I/O的事件循环中,达到两者的协调。
关键代码示例
import asyncio
import concurrent.futures
import time
# CPU密集型任务
def cpu_bound_task():
time.sleep(2) # 模拟CPU密集型计算
return "CPU task completed"
# 异步I/O任务
async def io_bound_task():
await asyncio.sleep(1) # 模拟异步I/O操作
return "I/O task completed"
async def main():
with concurrent.futures.ThreadPoolExecutor() as executor:
loop = asyncio.get_running_loop()
# 提交CPU密集型任务到线程池
cpu_result = await loop.run_in_executor(executor, cpu_bound_task)
io_result = await io_bound_task()
print(cpu_result)
print(io_result)
if __name__ == "__main__":
asyncio.run(main())
在上述代码中:
cpu_bound_task
是CPU密集型任务,使用time.sleep
模拟长时间计算。io_bound_task
是异步I/O任务,使用asyncio.sleep
模拟异步I/O操作。- 在
main
函数中,通过loop.run_in_executor
将cpu_bound_task
提交到ThreadPoolExecutor
线程池执行,同时执行异步I/O任务io_bound_task
,最后打印两个任务的结果。这样就实现了异步I/O操作和CPU密集型任务的协调并发执行。