我的代码中有一个对象引用的静态 HashSet,它必须禁止所有写入请求,直到给定方法运行(它仅将哈希集用于读取目的)。我已阅读 Thread 基础知识,但尚不清楚如何继续执行此操作。
谁能帮帮我?
您提到您已阅读 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();
}
}
您可以使用创建集合的只读视图Collections.unmodifiableSet
。只需将此视图传递给不需要写入集合的每个人。(UnsupportedOperationException
任何试图修改此视图的人都会被抛出。)
这是一个有趣的问题,通常情况正好相反。
如果您想要一个不可变的地图,直到某个魔术方法告诉应用程序的其余部分可以,您可以Collections.unmodifiableMap()
在初始化后使用它来创建地图的不可变副本。
当魔术方法运行时,它可以再次将地图替换为可修改的副本。
Map myMap;
public MyClass(Map myMap) {
this.myMap = Collections.unmodifiableMap(myMap);
}
synchronized public void releaseMyMap() {
myMap = new HashMap(myMap);
}
您可以从 Set 扩展并提供您自己的基于锁的实现(添加)来读取和写入 Set。
这将确保每当一个线程正在读取(在获取锁之后)没有其他线程可以写入它。
不完全确定是什么问题,但如果你只是想避免使用 HashSet 访问的并发问题,可能值得看看 ConcurrentSkipListSet。大多数操作都需要 log(n) 时间,但它不需要同步,也不会阻塞插入、删除和访问操作。总的来说,这可能会给你带来更好的表现。