我正在努力圍繞我的課程做一個線程安全的實現,以便在Servlet或代碼中的多個「客戶端」之間共享我的類。線程安全地更新共享對象而不會影響性能?
假裝我有以下MySingleton
類,這是一個用Configuration
對象初始化的單例。但是,可以觀察到Configuration
對象,因此如果發生更改,單身人士將訂閱通知。重要的關鍵點:
配置可隨時更改(無法預測)
當配置解析,它的值保存到MySingleton
的成員字段單元素的公共方法使用這些字段生成返回結果
請參閱下面的簡化代碼:
public class MySingleton
implements IConfigurationObserver {
// Member(s)
private static volatile MySingleton instance;
private final Configuration configuration;
private String firstParam;
private String secondParam;
// Constructor(s)
private MySingleton(Configuration configuration) {
this.configuration = configuration;
parseConfiguration();
configuration.addObserver(this);
}
public static MySingleton getInstance(Configuration configuration) {
// Perform synchronized creation if applicable (double locking technique)
MySingleton syncInstance = instance;
if (syncInstance == null) {
synchronized(MySingleton.class) {
syncInstance = instance; // Verify once again after synchronizing
if(syncInstance == null) {
syncInstance = new MySingleton(configuration);
instance = syncInstance;
}
}
}
return syncInstance;
}
// Private Method(s)
private void parseConfiguration() {
// Import values from the configuration
this.firstParam = configuration.get(0);
this.secondParam = configuration.get(1);
}
// Public Method(s)
public String buildSentence() {
// Build a new string based on values pulled from the configuration
StringBuilder strBuilder = new StringBuilder();
strBuilder.append(firstParam);
strBuilder.append(" - ");
strBuilder.append(secondParam);
return strBuilder.toString();
}
// Observer Method(s)
@Override
public void onConfigurationUpdated() {
// The configuration has changed. Parse it again.
parseConfiguration();
}
}
類適用於自己的罰款(單線程環境),但這裏的一些威脅,我想在多線程方案,以消除:
如果兩個更新到
Configuration
做在很短的時間內,有可能在第二次通話開始之前第一次撥打parseConfiguration()
尚未完成。這個很容易解決,我可以讓parseConfiguration()
同步(對吧?)。但是...當配置通知我們的單身人士時,假裝我們正在呼叫
buildSentence()
。我不希望buildSentence()
對firstParam和secondParam使用舊值的混合(即,如果parseConfiguration()
已完成)。因此,我可以爲parseConfiguration()
和buildSentence()
在Configuration
對象上放置一個同步塊,但後來我遇到了嚴重的性能問題:我不能有多個併發呼叫到buildSentence()
。說實話,對我來說,最理想的情況是:如果
buildSentence()
運行和Configuration
更新時,parseConfiguration()
要等到buildSentence()
是在運行之前如果
parseConfiguration()
正在運行,調用到buildSentence()
必須等到parseConfiguration()
結束開始然而之前,一旦
parseConfiguration()
結束後,我想允許多個線程運行buildSentence()
在同一時間。鎖定只能在更新即將發生或發生時纔會發生。
我如何重構MySingleton允許我上面列出的理想的「規則」?可能嗎?
我一直在想一個涉及信號量的解決方案。即:執行buildSentence()
時,檢查信號量是否可用。如果是的話,繼續(不阻擋)。如果否,請等待。並且parseConfiguration
會在執行期間鎖定信號量。但是,如果有人有直接的建議方法,我不想過度設計這個問題。讓我知道!
a good [resource](http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java/71399#71399)for java中的單身人士。 – 2014-08-29 06:33:42
僅供參考 - 我不認爲這個班級是單身人士的事實會對這個問題的正確答案產生任何影響。 – 2014-08-29 06:37:24
@Duncan你是對的。我可能會重新提出這個問題,使其更一般化。 – hbCyber 2014-08-29 06:39:43