【发布时间】:2016-01-26 00:38:50
【问题描述】:
我有一个看起来像这样的课程:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
public class ConnectionPool {
private HikariDataSource hds;
private final String propertyFileName;
public ConnectionPool(String propertyFileName) {
if (propertyFileName == null) {
throw new IllegalArgumentException("propertyFileName can't be null");
}
this.propertyFileName = propertyFileName;
reloadFile();
}
public void reloadFile() {
if (hds != null) {
hds.close();
}
hds = new HikariDataSource(new HikariConfig(propertyFileName));
}
public HikariDataSource getHikariDataSource() {
return hds;
}
public String getPropertyFileName() {
return propertyFileName;
}
public void executeQuery(final String sql, final CallBack<ResultSet, SQLException> callBack) {
new Thread(new Runnable() {
@Override
public void run() {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = hds.getConnection();
preparedStatement = connection.prepareStatement(sql);
resultSet = preparedStatement.executeQuery();
callBack.call(resultSet, null);
} catch (SQLException e) {
callBack.call(null, e);
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException ignored) {}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException ignored) {}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException ignored) {}
}
}
}
}).start();
}
public void executeUpdate(final String sql, final CallBack<Integer, SQLException> callBack) {
//TODO
}
public void execute(final String sql, final CallBack<Boolean, SQLException> callBack) {
//TODO
}
public void connection(final String sql, final CallBack<Connection, SQLException> callBack) {
//TODO
}
}
问题是reloadFile() 方法可以在使用hds 时从不同的线程调用。因此,当我在另一个线程中使用它的连接对象时,hds 可能已关闭。解决这个问题的最佳方法是什么?我应该在创建新的HikariDataSource 对象后等待几秒钟,然后再关闭旧对象(直到查询完成)?
编辑:另一个问题:hds 是否应该是volatile,这样hds 的更改对所有线程都是可见的?
【问题讨论】:
-
对于“易失性”:是的,您应该这样做。但是,将其设置为 volatile 并不能解决所有问题:原始 ds 仍然可能已关闭,但您尚未将其分配给新数据源。在那一刻,正在获得连接的线程将从封闭的数据源中获取,您的代码应该能够应对这种情况。而且,如果您的代码能够应对这种情况,那么不将其更改为 volatile 并不是什么大问题
标签: java concurrency thread-safety connection-pooling hikaricp