线程安全单例类 [英] Thread Safe singleton class

查看:28
本文介绍了线程安全单例类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 the getInstance() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆