gpt4 book ai didi

java - 线程安全单例类

转载 作者:IT老高 更新时间:2023-10-28 20:22:17 24 4
gpt4 key购买 nike

我写了一个下面的单例类。我不确定这是否是线程安全的单例类?

public class CassandraAstyanaxConnection {

private static CassandraAstyanaxConnection _instance;
private AstyanaxContext<Keyspace> context;
private Keyspace keyspace;
private ColumnFamily<String, String> emp_cf;



public static synchronized CassandraAstyanaxConnection getInstance() {
if (_instance == null) {
_instance = new CassandraAstyanaxConnection();
}
return _instance;
}

/**
* Creating Cassandra connection using Astyanax client
*
*/
private CassandraAstyanaxConnection() {

context = new AstyanaxContext.Builder()
.forCluster(ModelConstants.CLUSTER)
.forKeyspace(ModelConstants.KEYSPACE)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2"))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());

context.start();
keyspace = context.getEntity();

emp_cf = ColumnFamily.newColumnFamily(
ModelConstants.COLUMN_FAMILY,
StringSerializer.get(),
StringSerializer.get());
}

/**
* returns the keyspace
*
* @return
*/
public Keyspace getKeyspace() {
return keyspace;
}

public ColumnFamily<String, String> getEmp_cf() {
return emp_cf;
}
}

谁能帮我解决这个问题?对我上面的 Singleton 类的任何想法都会有很大帮助。

更新代码:-

我正在尝试在我的代码中加入波西米亚建议。这是更新的代码,我得到了-

public class CassandraAstyanaxConnection {
private static class ConnectionHolder {
static final CassandraAstyanaxConnection connection = new CassandraAstyanaxConnection();
}
public static CassandraAstyanaxConnection getInstance() {
return ConnectionHolder.connection;
}
/**
* Creating Cassandra connection using Astyanax client
*
*/
private CassandraAstyanaxConnection() {
context = new AstyanaxContext.Builder()
.forCluster(ModelConstants.CLUSTER)
.forKeyspace(ModelConstants.KEYSPACE)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2"))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getEntity();
emp_cf = ColumnFamily.newColumnFamily(
ModelConstants.COLUMN_FAMILY,
StringSerializer.get(),
StringSerializer.get());
}
/**
* returns the keyspace
*
* @return
*/
public Keyspace getKeyspace() {
return keyspace;
}
public ColumnFamily<String, String> getEmp_cf() {
return emp_cf;
}
}

谁能看一下,让我知道这次我做对了吗?

感谢您的帮助。

最佳答案

您正在实现 lazy initialization模式 - 首次使用时创建实例的位置。

但是有一个简单的技巧可以让你编写一个线程安全的实现,不需要同步!它被称为 Initialization-on-demand holder idiom ,它看起来像这样:

public class CassandraAstyanaxConnection {

private CassandraAstyanaxConnection(){ }

private static class Holder {
private static final CassandraAstyanaxConnection INSTANCE = new CassandraAstyanaxConnection();
}

public static CassandraAstyanaxConnection getInstance() {
return Holder.INSTANCE;
}
// rest of class omitted
}

此代码在第一次调用 getInstance() 时初始化实例,重要的是,由于类加载器的约定,不需要同步:

  • 类加载器在第一次访问类时加载类(在这种情况下,Holder 的唯一访问权限是在 getInstance() 方法内)
  • 当一个类被加载,并且在任何人可以使用它之前,所有的静态初始化器都保证被执行(那是 Holder 的静态 block 触发的时候)
  • 类加载器有自己的内置同步机制,保证上述两点是线程安全的

这是我在需要延迟初始化时使用的一个巧妙的小技巧。您还可以获得 final 实例的好处,即使它是惰性创建的。还要注意代码是多么干净和简单。

编辑:您应该将所有构造函数设置为私有(private)或 protected 。设置和清空私有(private)构造函数将完成工作

关于java - 线程安全单例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16106260/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com