线程安全单例类 [英] Thread Safe singleton class
问题描述
我写了一个下面的Singleton类。我不确定这是否是线程安全的单例类?
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.
编辑:您应将所有构造函数设置为private或protected。设置和清空私有构造函数将完成工作
You should set all constructors as private or protected. Setting and empty private constructor will do the work
这篇关于线程安全单例类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!