コードにオブジェクト参照の静的HashSetがあり、特定のメソッドが実行されるまですべての書き込み要求を禁止する必要があります(読み取り目的でのみハッシュセットを使用します)。スレッドの基本を読みましたが、これを実行する方法がまだわかりません。
誰か助けてくれませんか?
スレッドの基本を読んだとおっしゃっていたので、セットに複数のリーダーやライターがあるマルチスレッドアプリがあると思います。読み取り/書き込みロックを使用して、コレクションへのアクセスを制限できます。指定されたメソッドが実行されると、読み取りロックがロックされます。これにより、他のユーザーは読み取りを許可されますが、書き込みは許可されません。以下の方法 (または同様の方法) を使用して書き込む限り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);
}
何が問題なのか正確にはわかりませんが、HashSet を使用してアクセスする際の同時実行の問題を回避しようとしている場合は、おそらく ConcurrentSkipListSet を確認する価値があります。ほとんどの操作で log(n) 時間がかかりますが、同期は必要なく、挿入、削除、およびアクセス操作でブロックされません。全体として、パフォーマンスが向上する可能性があります。
Set から拡張し、独自のロック ベースの (追加の) 実装を提供して、Set の読み取りと書き込みを行うことができます。
これにより、スレッドが (ロックを取得した後に) 読み取りを行っているときはいつでも、他のスレッドがそのスレッドに書き込むことができなくなります。