需求由来
(1)sql都是依靠jdbc提供的connection .execute(sql)执行的,获取connection 途径:
Connection connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
但是一个connection同时只能被一个线程执行excute(),否则可能存在竞态条件
(2)connection的创建是比较消耗资源,所以可以创建一个装connection的“池”,存入一些实例化好的connection,需要的时候从池中取出,使用完成后释放到池中
池的功能点
(1)持有一个connection的容器
(2)创建connection
(3)获取connection
(4)释放connection
(5)保证每次获取connection都是竞态安全的
注意问题
(1)创建connection、获取connection应该保证pooledConnections的线程安全,所以需要使用synchronized的如【一】【二】
(2)释放connection只需要将PooledConnection isBusy 设置为false即可,由于connection被独立线程持有,所以释放不存在竞态条件【三】;设置为busy状态是从连接池中获取,所以应当由连接池保证竞态安全【四】
代码片段
public class PooledConnection {
private Connection connection;
private boolean isBusy = false;
【三】
public void closeConnection(){
// PooledConnection 线程独立,可以自己修改isBusy状态
isBusy =false;
}
}
public class DefaultPool implements Pool{
private Vector<PooledConnection> pooledConnections = new Vector<>();
String jdbcUrl;
String jdbcUsername;
String jdbcPassword;
int initCount;
int step;
int maxCount;
public DefaultPool() {
try{
Class.forName(Conf.jdbcDriver);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
createPooledConnection(initCount);
}
@Override
public PooledConnection getPooledConnection() {
PooledConnection pooledConnection = getRealConnctionFromPool();
while (pooledConnection == null){
return createPooledConnection(step);
}
return pooledConnection;
}
【一】
@Override
public synchronized PooledConnection createPooledConnection(int count) {
if(pooledConnections.size() > maxCount){
throw new RuntimeException("线程池已满");
}
PooledConnection pooledConnection = null;
for(int i = 0; i < count ; i++){
try{
Connection connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
pooledConnection = new PooledConnection(connection, false);
pooledConnections.add(pooledConnection);
}catch (SQLException e){
e.printStackTrace();
}
}
return pooledConnection;
}
【二】
private synchronized PooledConnection getRealConnctionFromPool(){
for(PooledConnection pooledConnection : pooledConnections){
// 可能会出现脏读,因为releaseConnect()更新的值,可能还没有刷到共享缓存
if(pooledConnection.isBusy()){
continue;
}
try{
if(pooledConnection.getConnection().isValid(3000)){
// 使用busy来标志连接是否可用的
pooledConnection.setBusy(true);
return pooledConnection;
}
Connection connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
pooledConnection.setConnection(connection);
【四】
pooledConnection.setBusy(true);
return pooledConnection;
}catch (SQLException e){
e.printStackTrace();
}
}
// 返回为空的潜台词就是要准备创建新的连接了
return null;
}
}