【问题标题】:HikariCP Wrapper (thread safety)HikariCP Wrapper(线程安全)
【发布时间】:2015-04-20 01:55:13
【问题描述】:

我正在学习使用 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经验,所以我需要你的建议。 一流(原始)线程安全吗? 我的实现线程安全吗?

【问题讨论】:

  • 一切都是线程安全的。不过,我会更改代码以使其尊重 Java 命名约定:数学以小写字母开头,变量不包含下划线。 getConnection() 不应该抛出异常,而是 SQLException。静态块中的 try/catch 是没用的,因为构造函数不会抛出任何异常。
  • @JBNizet 谢谢。那么我可以跳过方法 init() 和 getConnection() 中的同步吗? (我会根据您的建议更新代码)。
  • 没有。删除它们会使代码不是线程安全的。
  • @JBNizet 哦,我不明白你的第一条评论。谢谢。

标签: java thread-safety singleton wrapper hikaricp


【解决方案1】:

HikariCP 本身是线程安全的。据我了解,您要做的是在通过 HikariDataSource 方法初始化 HikariDataSource 之前阻止调用者 getConnection() 。大概您还想防止多次调用init() 数据源。

就池吞吐量而言,使用同步包装 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!!!!!."); 
  }
}

【讨论】:

  • "HikariCP 本身是线程安全的。"这是从哪里来的?如果您依赖未记录的实施细节,请说明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2021-07-12
  • 2011-03-30
  • 1970-01-01
  • 1970-01-01
  • 2012-09-03
相关资源
最近更新 更多