线程安全单例类

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

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课程的想法都会有很大的帮助。

更新的代码: –

我正试图在我的代码中join波希米亚的build议。 这里是更新的代码,我得到了 –

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

任何人都可以看看,让我知道,如果这一次我得到它的权利或不?

谢谢您的帮助。

您正在实现延迟初始化模式 – 第一次使用时创build实例的位置。

但是有一个简单的技巧,可以让你编写一个不需要同步的线程安全实现! 它被称为按需初始化持有者习惯用法 ,它看起来像这样:

 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的静态块触发时)
  • 类加载器有自己的同步内置,使上述两点保证线程安全

每当我需要延迟初始化时,我都会使用这个小技巧。 即使它是懒惰创build的,也可以获得final实例的奖金。 还要注意代码是多么干净和简单。

编辑:你应该设置所有的构造函数为私有或受保护的。 设置和清空私人构造函数将完成这项工作

以上所有方法都是急切地初始化对象。 这个怎么样。 这将帮助你懒惰地初始化你的类。 你可能有沉重的对象,你不想在启动时初始化。

 public class MySinglton { private MySinglton (){} private static volatile MySinglton s; public static MySinglton getInstance(){ if (s != null ) return s; synchronized(MySinglton.class){ if (s == null ) { s = new MySinglton(); } } return s; } } 

不,如果在pulbic方法上返回的值是可变对象,则它不是线程安全的。

对于这个类是线程安全的一种方法是将其改变为不可变的。

要做到这一点,你可以改变这样的方法:

 public Keyspace getKeyspace() { // make a copy to prevent external user to modified or ensure that Keyspace is immutable, in that case, you don't have to make a copy return new Keyspace( keyspace ); } public ColumnFamily<String, String> getEmp_cf() { // Same principle here. If ColumnFamily is immutable, you don't have to make a copy. If its not, then make a copy return new ColumnFamily( emp_cf ); } 

在本书的Java并发实践中,您可以看到不变性的原则。

不,这似乎不是线程安全的。 看起来,在调用getInstance之后,您可以访问可变数据,其中锁将被释放。

正如在这篇伟大的文章中提到的那样:

这个问题的最佳解决scheme是使用静态字段

 public class Singelton { private static final Singelton singleObject = new Singelton(); public Singelton getInstance(){ return singleObject; } } 

我认为这将做同样的事情,而不必每次都检查。 静态与第一次检查相同

 public class Singl { private static Singl _instance; //other vars static{ //synchronized(Singl.class){//do not need _instance = new Singl(); //} } public static Singl getInstance() { return _instance; } private Singl(){ //initizlize } }