我有以下代码,我正在尝试编写LRU缓存。我有一个跑步者类,我正在对缓存的随机容量运行。但是,缓存大小超过容量。当我使FixLRU方法同步时,当缓存大小超过100时它变得更准确但是它变得更慢。当我删除synchronized关键字时,缓存变得不那么准确。
如何使这项工作正常?更准确的?
import java.util.concurrent.ConcurrentHashMap;
public abstract class Cache<TKey, TValue> implements ICache<TKey,TValue>{
private final ConcurrentHashMap<TKey,TValue> _cache;
protected Cache()
{
_cache= new ConcurrentHashMap<TKey, TValue>();
}
protected Cache(int capacity){
_cache = new ConcurrentHashMap<TKey, TValue>(capacity);
}
@Override
public void Put(TKey key, TValue value) {
_cache.put(key, value);
}
@Override
public TValue Get(TKey key) {
TValue value = _cache.get(key);
return value;
}
@Override
public void Delete(TKey key) {
_cache.remove(key);
}
@Override
public void Purge() {
for(TKey key : _cache.keySet()){
_cache.remove(key);
}
}
public void IterateCache(){
for(TKey key: _cache.keySet()){
System.out.println("key:"+key+" , value:"+_cache.get(key));
}
}
public int Count()
{
return _cache.size();
}
}
import java.util.concurrent.ConcurrentLinkedQueue;
public class LRUCache<TKey,TValue> extends Cache<TKey,TValue> implements ICache<TKey, TValue> {
private ConcurrentLinkedQueue<TKey> _queue;
private int capacity;
public LRUCache(){
_queue = new ConcurrentLinkedQueue<TKey>();
}
public LRUCache(int capacity){
this();
this.capacity = capacity;
}
public void Put(TKey key, TValue value)
{
FixLRU(key);
super.Put(key, value);
}
private void FixLRU(TKey key)
{
if(_queue.contains(key))
{
_queue.remove(key);
super.Delete(key);
}
_queue.offer(key);
while(_queue.size() > capacity){
TKey keytoRemove =_queue.poll();
super.Delete(keytoRemove);
}
}
public TValue Get(TKey key){
TValue _value = super.Get(key);
if(_value == null){
return null;
}
FixLRU(key);
return _value;
}
public void Delete(TKey key){
super.Delete(key);
}
}
public class RunningLRU extends Thread{
static LRUCache<String, String> cache = new LRUCache<String, String>(50);
public static void main(String [ ] args) throws InterruptedException{
Thread t1 = new RunningLRU();
t1.start();
Thread t2 = new RunningLRU();
t2.start();
Thread t3 = new RunningLRU();
t3.start();
Thread t4 = new RunningLRU();
t4.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(cache.toString());
cache.IterateCache();
System.out.println(cache.Count());
}
@Override
public void run() {
for(int i=0;i<100000;i++)
cache.Put("test"+i, "test"+i);
}
}
答案 0 :(得分:2)
我会在添加您的条目后清理其他条目。这样可以最大限度地缩短缓存大于您想要的时间。您还可以触发size()来执行清理。
有关如何使其正常工作的任何想法?
您的测试是否反映了您的应用程序的行为方式?当您没有锤击它时,缓存可能正常(或更接近它)。 ;)
如果此测试确实反映了您的应用程序行为,则可能LRUCache不是最佳选择。
答案 1 :(得分:2)
您的问题似乎是您没有使用put方法putIfAbsent()
的特殊 synchronized 版本。如果您不使用它,则ConcurrentHashMap
的行为就像不同步一样 - 就像普通的地图,例如HashMap。
当您使用它时,您必须继续仅使用返回的值,因此您的Put()
方法没有正确的签名(它应该返回{{1} })支持并发。您需要重新设计界面。
此外,在java land中,与.Net land不同,我们使用前导小写命名我们的方法,例如TValue
,而不是put()
。因此,您可以重命名您的方法。