HikariCP包装器(线程安全) [英] HikariCP Wrapper (thread safety)

查看:289
本文介绍了HikariCP包装器(线程安全)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习使用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()数据源.

在池吞吐量方面,通常用同步方法包装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!!!!!."); 
  }
}

I'm learning to use HikariCP (i'm new in java) and i found a wrapper but i think it's not thread safety, well the instance of the singleton is thread safety but not the method getConnection(). The class is this:

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();  
    }  
}

Well, i've needed to send arguments to HikariConfig or HikariDataSource so I've re-write it this way:

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();
    }

}

I use it this way:

IConnectionProvider connectionProvider = ConnectionProviderHikariCP.getInstance();
connectionProvider.init(url, user, passwd);

BaseDAOFactory fatory = new MySqlDAOFactory(connectionProvider);
IExerciseBO exerciseBO = new ExerciseBO(fatory); 

But I'm not experienced in java so I need your advice. Is first class (the original) thread safety? Is my implementation thread safety?

解决方案

HikariCP itself is thread-safe. As I understand it, what you are trying to do is prevent callers to getConnection() before the HikariDataSource has been initialized via the init() method. Presumably you also want to prevent multiple calls to init() the datasource.

Wrapping getConnection() with a synchronized is a bad idea in general with respect to pool throughput. I recommend the following pattern, based on your code above:

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包装器(线程安全)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆