面试题答案
一键面试Python多线程适用于I/O密集型任务的原因
- GIL(全局解释器锁)影响:Python的多线程在CPU密集型任务中会受到GIL的限制,因为GIL同一时刻只允许一个线程在CPU上执行字节码,无法利用多核优势。但在I/O密集型任务中,线程在进行I/O操作(如文件读写、网络请求等)时,会释放GIL,使得其他线程有机会获取GIL并执行,从而实现多个I/O操作的并发执行,提高整体效率。
- I/O操作特性:I/O操作通常比CPU计算慢得多,在等待I/O操作完成的过程中,线程处于空闲状态。多线程可以在一个线程等待I/O时,切换到其他线程执行,充分利用这段等待时间,提升程序的整体运行效率。
使用threading
模块实现简单I/O密集型多线程任务(同时读取多个文件内容)
import threading
def read_file(file_path):
try:
with open(file_path, 'r') as file:
content = file.read()
print(f"Read content from {file_path}: {content}")
except FileNotFoundError:
print(f"File {file_path} not found.")
if __name__ == '__main__':
file_paths = ['file1.txt', 'file2.txt', 'file3.txt']
threads = []
for file_path in file_paths:
thread = threading.Thread(target=read_file, args=(file_path,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
在上述代码中:
- 定义了
read_file
函数,该函数接受一个文件路径作为参数,尝试打开文件并读取其内容。如果文件不存在,则捕获FileNotFoundError
并打印提示信息。 - 在
if __name__ == '__main__':
代码块中,首先定义了一个包含多个文件路径的列表file_paths
。 - 然后,通过循环为每个文件路径创建一个新的线程,线程的目标函数为
read_file
,并将文件路径作为参数传递给目标函数。创建线程后启动线程。 - 最后,通过另一个循环调用每个线程的
join
方法,等待所有线程完成,确保主线程在所有文件读取操作完成后再退出。