我使用LinkedHashMap编写了一个LRU缓存。我用它来缓存一些内存表。表大小从几行到几千行不等。为了更精确地控制内存,我设置了最大缓存行而不是最大表。缓存在多线程上下文中运行。我在JDK7和JDK8中测试代码。他们有完全不同的结果。在JDK7中,似乎内存泄漏非常快。在JDK8中,它运行非常稳定,没有内存泄漏。有人可以帮忙吗?我无法相信JDK 7有如此严重的错误!
以下是代码:
public class TableLRUCache<K>
{
private String cacheName;
private TableLRUCache.InternalMap container;
public TableLRUCache(String cacheName, int cacheSize)
{
this.cacheName = cacheName;
container = new TableLRUCache.InternalMap(cacheSize);
}
public synchronized TableWrapper get(K k)
{
TableWrapper result = (TableWrapper) container.get(k);
if (result != null)
{
result.hit();
}
return result;
}
public synchronized TableWrapper put(K k, TableWrapper tableWrapper)
{
TableWrapper result = container.put(k, tableWrapper);
Iterator<Map.Entry<K, TableWrapper>> it = container.entrySet().iterator();
while (it.hasNext())
{
if (container.totalRows <= container.maxRows)
{
break;
}
Map.Entry<K, TableWrapper> entry = it.next();
if (!entry.getValue().isPersist())
{
//the table has not persistent, delete it later.
continue;
}
it.remove();
updateTableSurviveStatistic(entry.getValue());
BaseTable deleteTable = entry.getValue().table;
if (deleteTable != null)
{
container.totalRows -= deleteTable.getRows().size();
}
}
return result;
}
public synchronized TableWrapper remove(K k)
{
TableWrapper result = container.remove(k);
if (result != null)
{
updateTableSurviveStatistic(result);
}
return result;
}
private void updateTableSurviveStatistic(TableWrapper tableWrapper)
{
//update statistic
}
public synchronized String statistic()
{
// get statistic
return null;
}
public synchronized int getCacheSize()
{
return container.maxRows;
}
public synchronized int getUsedRows()
{
return container.totalRows;
}
public class InternalMap<K> extends LinkedHashMap<K, TableWrapper>
{
private int maxRows;
private int totalRows = 0;
public InternalMap(int cacheSize)
{
super(16, (float) 0.75, true);
this.maxRows = cacheSize;
}
@Override
public TableWrapper put(K key, TableWrapper tableWrapper)
{
TableWrapper old = this.remove(key);
if (old != null)
{
totalRows -= old.table.getRows().size();
}
if (tableWrapper != null)
{
totalRows += tableWrapper.table.getRows().size();
}
return super.put(key, tableWrapper);
}
@Override
public TableWrapper remove(Object key)
{
TableWrapper result = super.remove(key);
if (result != null)
{
totalRows -= result.table.getRows().size();
}
return result;
}
}
}