我在我的代碼中有一個靜態的HashSet對象引用,它必須在給定的方法正在運行之前不允許所有寫入請求(它僅將哈希集用於讀取目的)。我已閱讀線程基礎知識,但尚不清楚如何繼續這樣做。在Java中鎖定哈希集合
任何人都可以幫我嗎?
我在我的代碼中有一個靜態的HashSet對象引用,它必須在給定的方法正在運行之前不允許所有寫入請求(它僅將哈希集用於讀取目的)。我已閱讀線程基礎知識,但尚不清楚如何繼續這樣做。在Java中鎖定哈希集合
任何人都可以幫我嗎?
您提到您已閱讀線程基礎知識,因此我假設您有一個多線程應用程序,您有多個閱讀器和/或作者。您可以使用讀寫鎖來限制對該集合的訪問。當給定的方法執行時,它鎖定讀取鎖定,允許其他人讀取,但不寫入。只要您使用下面的putInSet
方法(或類似方法)編寫代碼,就可以要求寫入鎖寫入。然後在讀鎖被保持時,該組不能寫入。
private final Set<Object> mySet = new HashSet<Object>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public void methodThatRunsAndAllowsReadOnly() {
lock.readLock().lock();
try {
// method body here
}
finally {
lock.readLock().unlock();
}
}
public void putInSet(Object o) {
lock.writeLock().lock();
try {
mySet.add(o);
}
finally {
lock.writeLock().unlock();
}
}
+1使用讀寫鎖。 – 2010-10-11 22:28:02
我正在查看ReentrantReadWriteLock的javadocs,它說,如果不首先釋放讀取鎖定,則無法升級到寫入鎖定。您可能需要釋放讀取鎖定作爲putInSet()中的第一行,然後在釋放寫入鎖定之前重新獲取finally中的讀取鎖定。 – InverseFalcon 2011-09-16 23:56:00
您可以使用Collections.unmodifiableSet
創建該設備的只讀視圖。只需將此視圖傳遞給不需要寫入集合的所有人即可。 (對於任何試圖修改此視圖的人,都將引發UnsupportedOperationException
)。
這是一個有趣的問題,通常情況下是相反的。
如果你想要一個不變的映射,直到某個魔術方法告訴應用程序的其餘部分它可以,那麼可以使用Collections.unmodifiableMap()
在初始化後創建映射的不可變副本。
當magic方法運行時,它可以用一個可修改的副本再次替換地圖。
Map myMap;
public MyClass(Map myMap) {
this.myMap = Collections.unmodifiableMap(myMap);
}
synchronized public void releaseMyMap() {
myMap = new HashMap(myMap);
}
您可以從一個集合擴展並提供您自己的基於鎖定的實現(添加)讀取和寫入集合。
這將確保無論何時一個線程正在讀取(在獲取鎖定之後),其他線程都不能寫入它。
不完全確定問題所在,但如果您只是試圖避免使用HashSet訪問併發問題,可能值得看看ConcurrentSkipListSet。大部分操作需要log(n)時間,但不需要同步,並且不會在插入,刪除和訪問操作時阻塞。在整體上可能會給你更好的表現。
什麼意思是不允許的?塊?拋出異常? – 2010-10-11 17:21:39
拼寫檢查:我想不是「在給定方法運行之前不允許所有寫請求」應該是「在給定方法運行時不允許所有寫請求」? – 2010-10-11 17:29:17
此外,使用示例代碼發佈您的問題會很有幫助 - 使您的問題更清晰易懂,並且更易於回答。 – 2010-10-11 17:30:10