线程安全单例类 [英] Thread Safe singleton class
问题描述
我写了一个下面的单例类.我不确定这是否是线程安全的单例类?
I wrote a below Singleton class. I am not sure whether this is thread safe singleton class or not?
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 类的任何想法都会有很大帮助.
Can anyone help me with this? Any thoughts on my above Singleton class will be of great help.
更新代码:-
我正在尝试在我的代码中加入波西米亚风格的建议.这是更新的代码,我得到了-
I am trying to incorporate Bohemian suggestion in my code. Here is the updated code, I got-
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;
}
}
谁能看一下,让我知道这次我做对了没有?
Can anyone take a look and let me know if this time I got it right or not?
感谢您的帮助.
推荐答案
您正在实施 懒惰初始化 模式 - 在第一次使用时创建实例.
You are implementing the lazy initialization pattern - where the instance is created when first used.
但是有一个简单的技巧可以让您编写一个不需要同步的线程安全实现!它被称为按需初始化持有人习语,它看起来像这样:
But there is a simple trick that allows you to code a threadsafe implementation that doesn't require synchronization! It is known as the Initialization-on-demand holder idiom, and it looks like this:
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()
时初始化实例,重要的是不需要同步,因为类加载器的契约:
This code initializes the instance on the first calling of getInstance()
, and importantly doesn't need synchronization because of the contract of the class loader:
- 类加载器在第一次访问时加载类(在这种情况下,
Holder
的唯一访问是在getInstance()
方法内) - 当一个类被加载时,在任何人都可以使用它之前,所有的静态初始化器都保证会被执行(这就是
Holder
的静态块触发的时候) - 类加载器内置了自己的同步机制,可以保证上述两点是线程安全的
- the class loader loads classes when they are first accessed (in this case
Holder
's only access is within thegetInstance()
method) - when a class is loaded, and before anyone can use it, all static initializers are guaranteed to be executed (that's when
Holder
's static block fires) - the class loader has its own synchronization built right in that make the above two points guaranteed to be threadsafe
这是我在需要延迟初始化时使用的一个巧妙的小技巧.您还可以获得 final
实例的奖励,即使它是惰性创建的.还要注意代码是多么干净和简单.
It's a neat little trick that I use whenever I need lazy initialization. You also get the bonus of a final
instance, even though it's created lazily. Also note how clean and simple the code is.
您应该将所有构造函数设置为私有或受保护.设置和空私有构造函数将完成工作
You should set all constructors as private or protected. Setting and empty private constructor will do the work
这篇关于线程安全单例类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!