HikariCP Wrapper(线程安全)
我正在学习使用HikariCP(我是java的新手),我发现了一个包装器,但我认为它不是线程安全,单例的实例是线程安全,但不是方法getConnection()。 这个课是这样的:
public class HikariCPWrapper{ private static final HikariCPWrapper INSTANCE; private HikariDataSource ds; static { INSTANCE = new HikariCPWrapper(); } private HikariCPWrapper(){ HikariConfig config = new HikariConfig(); //config.set... //... ds = new HikariDataSource(config); } public static HikariCPWrapper getInstance () { return INSTANCE; } public Connection getConnection() throws SQLException { return ds.getConnection(); } }
好吧,我需要向HikariConfig或HikariDataSource发送参数,所以我用这种方式重写它:
public interface IConnectionProvider { void init(String jdbcUrl, String user, String password); Connection getConnection() throws SQLException; } public class ConnectionProviderHikariCP implements IConnectionProvider{ private static final ConnectionProviderHikariCP INSTANCE; private final HikariDataSource hikariDataSource; private Boolean initialized; //class initializer: static { INSTANCE = new ConnectionProviderHikariCP(); } private ConnectionProviderHikariCP() { hikariDataSource = new HikariDataSource(); initialized = false; } public static ConnectionProviderHikariCP getInstance() { return INSTANCE; } @Override public synchronized void init(String jdbcUrl, String user, String password) { hikariDataSource.setJdbcUrl(jdbcUrl); hikariDataSource.setUsername(user); hikariDataSource.setPassword(password); initialized = true; } @Override public synchronized Connection getConnection() throws SQLException { if(!initialized) throw new UnsupportedOperationException("Debe inicializar mediante el método Init() primero!!!!!."); return hikariDataSource.getConnection(); } }
我这样使用它:
IConnectionProvider connectionProvider = ConnectionProviderHikariCP.getInstance(); connectionProvider.init(url, user, passwd); BaseDAOFactory fatory = new MySqlDAOFactory(connectionProvider); IExerciseBO exerciseBO = new ExerciseBO(fatory);
但我没有java经验,所以我需要你的建议。 是头等(原始)线程安全吗? 我的实现线程安全吗?
HikariCP本身是线程安全的。 据我了解,你要做的是在通过init()
方法初始化HikariDataSource
之前阻止调用者获取getConnection()
。 据推测,您还希望阻止对init()
数据源的多次调用。
在池吞吐量方面,使用synchronized包装getConnection()
通常是个坏主意。 我推荐以下模式,基于上面的代码:
public class ConnectionProviderHikariCP implements IConnectionProvider { private static final ConnectionProviderHikariCP INSTANCE; private final HikariDataSource hikariDataSource; private AtomicBoolean initialized; //class initializer: static { INSTANCE = new ConnectionProviderHikariCP(); } private ConnectionProviderHikariCP() { hikariDataSource = new HikariDataSource(); initialized = new AtomicInteger(); } public static ConnectionProviderHikariCP getInstance() { return INSTANCE; } @Override public void init(String jdbcUrl, String user, String password) { if (initialized.compareAndSet(false, true)) { hikariDataSource.setJdbcUrl(jdbcUrl); hikariDataSource.setUsername(user); hikariDataSource.setPassword(password); } else { throw new IllegalStateException("Connection provider already initialized."); } } @Override public Connection getConnection() throws SQLException { if (initialized.get()) { return hikariDataSource.getConnection(); } throw new UnsupportedOperationException("Debe inicializar mediante el método Init() primero!!!!!."); } }