我的代码中有一个静态的HashSet对象引用,它必须禁止所有写入请求,直到给定的方法运行(它仅将hashset用于读取目的)。我已经阅读了Thread基础知识,但我还不清楚如何继续这样做。
有人可以帮帮我吗?
答案 0 :(得分:9)
你提到你已经阅读了Thread基础知识,所以我假设你有一个多线程应用程序,你有多个读者和/或编写者。您可以使用读写锁来限制对集合的访问。当给定方法执行时,它锁定读锁定,允许其他人读取但不写入。只要您使用下面的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 :(得分:6)
您可以使用Collections.unmodifiableSet
创建该集的只读视图。只需将此视图传递给不需要写入集合的所有人。 (对于试图修改此视图的任何人,将抛出UnsupportedOperationException
。)
答案 2 :(得分:1)
这是一个有趣的问题,通常是另一种方式。
如果你想要一个不可变的地图,直到某个魔术方法告诉应用程序的其余部分它没问题,你可以使用Collections.unmodifiableMap()
在初始化后创建地图的不可变副本。
当魔术方法运行时,它可以再次用可修改的副本替换地图。
Map myMap;
public MyClass(Map myMap) {
this.myMap = Collections.unmodifiableMap(myMap);
}
synchronized public void releaseMyMap() {
myMap = new HashMap(myMap);
}
答案 3 :(得分:0)
您可以从Set扩展并提供您自己的基于锁的实现(添加)来读取和写入Set。
这将确保无论何时线程正在读取(获取锁定后),其他线程都无法写入。
答案 4 :(得分:0)
不确定是什么问题,但是如果你只是试图避免使用HashSet访问并发问题,那么可能值得查看ConcurrentSkipListSet。大多数操作需要log(n)时间,但它不需要同步,也不会阻止插入,删除和访问操作。在整体上可能会给你更好的表现。