[英]Thread Safe singleton class
我寫了一個下面的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課程的任何想法都會有很大的幫助。
更新的代碼: -
我試圖在我的代碼中加入波希米亞建議。 這是更新后的代碼,我得到了 -
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;
}
}
任何人都可以看看,讓我知道,如果這次我做對了嗎?
謝謝您的幫助。
您正在實現延遲初始化模式 - 首次使用時創建實例。
但是有一個簡單的技巧,可以讓你的代碼並不需要同步的線程執行! 它被稱為按需初始化持有者習語 ,它看起來像這樣:
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
實例的獎勵,即使它是懶惰創建的。 還要注意代碼的清晰和簡單。
編輯:您應該將所有構造函數設置為私有或受保護。 設置和清空私有構造函數將完成工作
以上所有方法都在急切地初始化對象。 這個怎么樣。 這將幫助您懶惰地初始化您的類。 您可能有重物,並且您不希望在啟動時初始化。
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 Concurrency in Practice中,您可以看到該不變性的原理。
作為mentiond這篇大文章在這里 :
這個問題的最佳解決方案是使用靜態字段
public class Singelton {
private static final Singelton singleObject = new Singelton();
public Singelton getInstance(){
return singleObject;
}
}
不,這並不似乎是線程安全的。 看來你在調用getInstance
之后可以訪問可變數據,其中鎖已經被釋放。
在java 1.5版本之后我們可以使用volatile。 如果我們使用volatile java key ward,我們可以創建具有線程安全性的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!");
}
}
我認為這樣做會做同樣的事情,而不必每次都檢查一下。 static與第一次檢查相同
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
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.