为了账号安全,请及时绑定邮箱和手机立即绑定

线程安全单例类

线程安全单例类

幕布斯7119047 2019-12-11 09:09:02
我写了下面的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课堂上的任何想法都会有很大帮助。谁能看一下,让我知道这次是否正确?谢谢您的帮助。
查看完整描述

3 回答

?
智慧大石

TA贡献1946条经验 获得超3个赞

您正在实现惰性初始化模式-首次使用实例时在其中创建实例。


但是有一个简单的技巧,可以让你的代码,一个线程的实现并不需要同步!它称为“ 按需初始化持有人”习惯用法,它看起来像这样:


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静态块触发时)

类加载器内置了自己的同步功能,可以确保上述两点是线程安全的

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


编辑:您应该将所有构造函数设置为私有或受保护。设置并清空私有构造函数即可完成工作



查看完整回答
反对 回复 2019-12-12
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞


以上所有方法都急于初始化对象。这个怎么样。这将帮助您懒惰地初始化ur类。您可能有重物,并且不想在启动时进行初始化。


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;


}




查看完整回答
反对 回复 2019-12-12
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

不,如果在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并发实践》中,您可以了解这种不变性的原理。



查看完整回答
反对 回复 2019-12-12
  • 3 回答
  • 0 关注
  • 340 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信