我想知道什麼是最好的方法來解決這個問題。我有一個調用Web服務,並將結果存儲在本地內存中緩存,像一個(抽象地講)簡單的方法:現在同步一個特定的web服務調用
public Document callWebservice(SomeObject parameter) {
Document result = cache.get(parameter);
if (result == null) {
result = parse(retrieve(parameter));
cache.put(result);
}
return result;
}
,如果文檔是在緩存中,它可以只返回無問題很好。在單線程環境中,這種方法也可以正常工作。但是,在多線程環境中,每個線程都會轉到「其他」位,並多次調用Web服務。
我可能會在「其他」部分扔下一個synchronized塊,但我相信這是一個鎖太「寬」 - 整個法會調用,即使他們稱之爲完全不同的東西線程不可用。
它的優良如果web服務被調用兩次,只要該請求是不同的(即,SomeObject參數,在這種情況下)。
現在,問題:什麼是採取在這種情況下,最好的辦法?
我想過存儲參數在(線程)集合對象。如果參數的內容相同,它會產生相同的hashCode/equals結果,並且會在集合對象中找到,表明另一個線程已經處理了該請求。如果是這種情況,可以暫停調用線程,直到web服務返回。 (我不得不弄清楚如何讓調用線程等待)。這會在SomeObject
參數對象上鎖定嗎?例如:
private Map<SomeObject, SomeObject> currentlyProcessingItems = new ConcurrentHashMap<SomeObject, SomeObject>();
public Document callWebservice(SomeObject parameter) {
if (currentlyProcessedItems.contains(parameter)) {
parameter = currentlyProcessedItems.get(parameter);
} else {
currentlyProcessedItems.putIfAbsent(parameter);
}
synchronized(parameter) {
Document result = cache.get(parameter);
if (result == null) {
Document result = parse(retrieve(parameter));
cache.put(result);
}
currentlyProcessedItems.remove(parameter);
return result;
}
}
(注:跟蹤當前處理的請求,ConcurrentHashMap中的使用,並鎖定可能不是最優的或完全錯誤的邏輯)
不,我從來沒有真正完成了線程讀的書。我應該。
我敢肯定,這個特殊的問題是相當普遍的,我只是沒能找到答案。如果我可能會問,這種叫做什麼情況(即鎖定一個特定的物體)呢?
你在SomeObject上獲得了equals和hashCode? – 2011-01-24 16:36:34
是的,根據Commons Lang的HashCodeBuilder和EqualsBuilder,該參數有一個很好的`hasCode()`和`equals()`方法。它在內部也有一些對象,它也正確地實現了`hashCode()`和`equals()`。 – fwielstra 2011-01-25 14:35:20