以下のシングルトンクラスを書きました。これがスレッドセーフなシングルトンクラスであるかどうかわかりませんか?
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;
}
}
誰でもこれで私を助けることができますか?上記のシングルトンクラスに関するご意見は、大変参考になります。
更新コード:-
私は自分のコードにボヘミアンの提案を取り入れようとしています。これが更新されたコードです。
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;
}
}
誰もが見て、今回はそれが正しかったかどうかを教えてもらえますか?
助けてくれてありがとう。
lazy初期化 パターン-インスタンスが最初に使用されるときに作成される場所を実装しています。
しかし、同期を必要としないスレッドセーフ実装をコーディングできる簡単なトリックがあります! Initialization-on-demand holder idiom と呼ばれ、次のようになります。
_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
の静的ブロックが起動するとき)怠laな初期化が必要なときはいつでも使用する、ちょっとした小技です。また、final
インスタンスのボーナスも取得されますが、それは遅延して作成されます。また、コードがどれほどクリーンでシンプルであるかに注意してください。
Edit:すべてのコンストラクターをprivateまたはprotectedとして設定する必要があります。設定して空のプライベートコンストラクターが作業を行います
上記のすべてのメソッドは、オブジェクトを積極的に初期化しています。これはどう。これは、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;
}
}
いいえ、pulbicメソッドで返される値が変更可能なオブジェクトである場合、スレッドセーフではありません。
このクラスに対してスレッドセーフにする方法の1つは、不変に変更することです。
これを行うには、次のようにこのメソッドを変更できます。
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の同時実行性 その不変性の原理を見ることができます。
このすばらしい記事で言及されているように here :
public class Singelton { private static final Singelton singleObject = new Singelton(); public Singelton getInstance(){ return singleObject; } }
Java 1.5バージョンではvolatileを使用できます。volatileJava key wardを使用した場合、インスタンス変数はOtherと共有するため、スレッドセーフでsingltonクラスを作成できますスレッドも。
public class SingleWithThreadSafe {
// create an object static referance of SingleWithThreadSafe with volatile
private static volatile SingleWithThreadSafe instance = null;
// if we make the constructor private so that this class cannot be
// instantiated from out side of class
private SingleWithThreadSafe() {
}
// Get only object available
public static SingleWithThreadSafe getInstance() {
if (instance == null) {
instance = new SingleWithThreadSafe();
}
return instance;
}
public void showMessage() {
System.out.println("Hello World!");
}
}
いいえ、これはappearではなく、スレッドセーフです。ロックが解除されたgetInstance
の呼び出し後にアクセス可能な可変データがあるようです。