面试题答案
一键面试设计思路
- 异常处理:当线程在使用连接执行数据库操作抛出异常时,捕获异常进行处理。
- 连接池状态维护:确保异常发生后,将使用的连接正确归还到连接池,避免连接泄露。
- 避免死锁:使用锁机制来控制对连接池的访问,确保同一时间只有一个线程能对连接池进行关键操作(如获取和归还连接),但要注意锁的粒度,避免过度锁定导致死锁。
关键代码片段
import threading
import queue
import sqlite3
# 数据库连接池类
class ConnectionPool:
def __init__(self, max_connections=5):
self.max_connections = max_connections
self.pool = queue.Queue(maxsize=max_connections)
self.lock = threading.Lock()
for _ in range(max_connections):
self.pool.put(sqlite3.connect('example.db'))
def get_connection(self):
with self.lock:
return self.pool.get()
def return_connection(self, conn):
with self.lock:
self.pool.put(conn)
# 线程执行的函数
def worker(pool):
conn = None
try:
conn = pool.get_connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM some_table')
result = cursor.fetchall()
print(result)
except sqlite3.Error as e:
print(f"发生数据库异常: {e}")
finally:
if conn:
pool.return_connection(conn)
# 创建连接池实例
pool = ConnectionPool()
# 创建并启动多个线程
threads = []
for _ in range(3):
t = threading.Thread(target=worker, args=(pool,))
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
在上述代码中:
ConnectionPool
类实现了数据库连接池,使用queue.Queue
来管理连接,threading.Lock
来控制对连接池的访问。worker
函数模拟线程执行数据库操作,在try
块中获取连接执行操作,在except
块中捕获数据库异常,在finally
块中确保连接归还到连接池。- 主线程创建连接池实例,并启动多个线程执行
worker
函数。这样在异常发生时,能保证连接池状态正确且避免死锁,不影响其他线程对连接池的正常使用。