メモリ、ファイル、およびリモート サービスに支えられたキャッシュ ストアをアプリに構築しています。明示的な同期を避けて、ストアをシンプルに保ちながら、ブロッキングなどの動作の問題にデコレータを使用したい。
これは単純なキャッシュです。これは単なる例です。
import java.util.HashMap;
public class SimpleCache {
private HashMap<String,Object> store;
private final BlockingCacheDecorator decorator;
public SimpleCache(){
store = new HashMap<String,Object>();
decorator = new BlockingCacheDecorator(this);
}
//is NOT called directly, always uses decorator
public Object get(String key){
return store.get(key);
}
//is NOT called directly, always uses decorator
public void set(String key, Object value){
store.put(key, value);
}
//is NOT called directly, always uses decorator
public boolean isKeyStale(String key){
return !(store.containsKey(key));
}
//is NOT called directly, always uses decorator
public void refreshKey(String key){
store.put(key, new Object());
}
public BlockingCacheDecorator getDecorator(){
return decorator;
}
}
getDecorator()
get()
とset()
、 whileの同期isKeyStale()
を提供するデコレータを返し、デコレータがrefreshKey()
理由や方法を知らなくてもキーを更新する必要があるかどうかを確認できるようにします。hereから同期デコレータのアイデアを得ました。
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class BlockingCacheDecorator {
private SimpleCache delegate;
private final ReentrantReadWriteLock lock;
public BlockingCacheDecorator(SimpleCache cache){
delegate = cache;
lock = new ReentrantReadWriteLock();
}
public Object get(String key){
validateKey(key);
lockForReading();
try{
return delegate.get(key);
}finally{ readUnlocked(); }
}
public void setKey(String key, Object value){
lockForWriting();
try{
delegate.set(key,value);
}finally{ writeUnlocked(); }
}
protected void validateKey(String key){
if(delegate.isKeyStale(key)){
try{
lockForWriting();
if(delegate.isKeyStale(key))
delegate.refreshKey(key);
}finally{ writeUnlocked(); }
}
}
protected void lockForReading(){
lock.readLock().lock();
}
protected void readUnlocked(){
lock.readLock().unlock();
}
protected void lockForWriting(){
lock.writeLock().lock();
}
protected void writeUnlocked(){
lock.writeLock().unlock();
}
}
質問:
SimpleCache
デコレータを介してのみ使用されると仮定すると、コードはスレッドセーフですか?ReadWriteLock
同期されているクラスの外で宣言するのは悪い習慣ですか?SimpleCache.getDecorator()
キャッシュとデコレータ インスタンス間の 1 対 1 のマッピングが保証されるので、これで問題ないと思います。