面试题答案
一键面试- 安装必要库:
- 通常Python自带
threading
模块用于多线程处理。如果有更高级的异步需求,还可以考虑asyncio
库。在Django项目中,这些库一般无需额外安装,因为Python标准库默认包含threading
,asyncio
也是Python 3.4+的标准库。
- 通常Python自带
- 创建多线程任务函数:
- 在Django应用的某个模块(例如
utils.py
)中定义处理耗时任务的函数。例如:
import time def batch_data_processing(data_list): for data in data_list: # 模拟数据处理 time.sleep(1) print(f"Processing {data}")
- 在Django应用的某个模块(例如
- 在视图或其他合适位置使用多线程:
- 在视图函数中引入多线程:
from django.http import HttpResponse import threading from. import utils def my_view(request): data_list = [1, 2, 3, 4, 5] # 创建线程 thread = threading.Thread(target = utils.batch_data_processing, args=(data_list,)) # 启动线程 thread.start() return HttpResponse("Task started in a new thread.")
- 避免与Django主线程冲突:
- 数据库操作:
- Django的数据库连接是线程局部的,这意味着每个线程都有自己独立的数据库连接。但是要注意事务管理,避免在子线程中开启长事务影响主线程。如果子线程需要进行数据库操作,建议使用
atomic
装饰器或上下文管理器,例如:
from django.db import transaction def batch_data_processing(data_list): with transaction.atomic(): for data in data_list: # 数据库操作 pass
- Django的数据库连接是线程局部的,这意味着每个线程都有自己独立的数据库连接。但是要注意事务管理,避免在子线程中开启长事务影响主线程。如果子线程需要进行数据库操作,建议使用
- 共享资源:
- 避免在主线程和子线程之间共享可变的全局状态。如果必须共享,使用线程锁(
threading.Lock
)来保护共享资源。例如:
shared_variable = 0 lock = threading.Lock() def increment_shared_variable(): global shared_variable with lock: shared_variable += 1
- 避免在主线程和子线程之间共享可变的全局状态。如果必须共享,使用线程锁(
- 数据库操作:
- 合理管理多线程资源:
- 线程数量控制:
- 根据服务器的CPU核心数和内存等资源来合理设置线程数量。例如,对于CPU密集型任务,线程数量不宜超过CPU核心数;对于I/O密集型任务,可以适当增加线程数量。可以通过
multiprocessing.cpu_count()
获取CPU核心数。
- 根据服务器的CPU核心数和内存等资源来合理设置线程数量。例如,对于CPU密集型任务,线程数量不宜超过CPU核心数;对于I/O密集型任务,可以适当增加线程数量。可以通过
- 线程生命周期管理:
- 确保线程能够正确结束。如果线程中包含无限循环,要提供一种退出机制,例如设置一个标志变量,主线程可以修改该变量通知子线程退出。
stop_flag = False def long_running_task(): while not stop_flag: # 任务逻辑 pass
- 异常处理:
- 在子线程函数中捕获异常,避免异常导致整个进程崩溃。可以在子线程函数内部使用
try - except
块处理异常,例如:
def batch_data_processing(data_list): try: for data in data_list: # 处理逻辑 pass except Exception as e: print(f"Error in batch processing: {e}")
- 在子线程函数中捕获异常,避免异常导致整个进程崩溃。可以在子线程函数内部使用
- 线程数量控制: