HikariCP Wrapper(线程安全)

HikariCP Wrapper (thread safety)

我正在学习使用 HikariCP(我是 java 的新手),我找到了一个包装器,但我认为它不是线程安全的,单例的实例是线程安全的,但不是方法获取连接()。 class 是这样的:

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 方面没有经验,所以我需要您的建议。 firstclass(原文)是线程安全的吗? 我的实现线程安全吗?

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