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!!!!!."); } }