java 缓存算法,最频繁访问驻留缓存算法,驻留缓存算法

最频繁访问驻留缓存算法,驻留缓存算法

在搜索系统中,如何缓存搜索最频繁的1000个搜索结果?自定制的精准短文本搜索服务项目代码

本文利用了ConcurrentHashMap和AtomicLong实现了线程安全且支持高并发的最频繁访问驻留缓存算法,除了缓存功能,还提供了缓存状态查询接口,非常实用。

比如,在搜索管理界面可看到如下缓存状态:

缓存状态

最大缓存数量: 1000

当前缓存数量: 11

驱逐缓存次数: 0

命中缓存次数: 6

未命中缓存次数: 11

缓存命中比例: 35.294117 %

搜索缓存命中情况(11)

序号

搜索关键词

缓存命中次数

1

L

3

2

LYB

2

3

LY

1

4

LANGYB

0

5

X

0

6

LANG

0

7

XL

0

8

LAN

0

9

XLF

0

10

LANGY

0

11

XLFD

0

实现代码如下:

import java.util.Collections;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.atomic.AtomicInteger;

import java.util.concurrent.atomic.AtomicLong;

/**

* 最频繁访问驻留缓存算法

* Created by ysc on 7/18/16.

*/

public class ConcurrentLRUCache {

private int maxCacheSize;

private Map> cache = new ConcurrentHashMap<>();

private AtomicLong totalEvictCount = new AtomicLong();

private AtomicLong hitCount = new AtomicLong();

private AtomicLong notHitCount = new AtomicLong();

public ConcurrentLRUCache(int maxCacheSize) {

cache = new ConcurrentHashMap<>(maxCacheSize, 1, 10);

this.maxCacheSize = maxCacheSize;

}

public String getStatus(){

StringBuilder status = new StringBuilder();

long total = hitCount.get()+notHitCount.get();

status.append("最大缓存数量: ").append(maxCacheSize).append("\n")

.append("当前缓存数量: ").append(getActualCacheSize()).append("\n")

.append("驱逐缓存次数: ").append(totalEvictCount.get()).append("\n")

.append("命中缓存次数: ").append(hitCount.get()).append("\n")

.append("未命中缓存次数: ").append(notHitCount.get()).append("\n")

.append("缓存命中比例: ").append(total == 0 ? 0 : hitCount.get()/(float)total*100).append(" %\n");

return status.toString();

}

public String getKeyAndHitCount(){

StringBuilder status = new StringBuilder();

AtomicInteger i = new AtomicInteger();

cache.entrySet().stream().sorted((a,b)->b.getValue().getCount()-a.getValue().getCount()).forEach(entry->status.append(i.incrementAndGet()).append("\t").append(entry.getKey()).append("\t").append(entry.getValue().getCount()).append("\n"));

return status.toString();

}

public int getMaxCacheSize() {

return maxCacheSize;

}

public int getActualCacheSize() {

return cache.size();

}

public Map> getCache() {

return Collections.unmodifiableMap(cache);

}

public AtomicLong getTotalEvictCount() {

return totalEvictCount;

}

public long getHitCount() {

return hitCount.longValue();

}

public long getNotHitCount() {

return notHitCount.longValue();

}

public void put(K key, V value){

if(cache.size() >= maxCacheSize){

// evict count

int evictCount = (int)(maxCacheSize*0.1);

if(evictCount < 1){

evictCount = 1;

}

totalEvictCount.addAndGet(evictCount);

cache.entrySet().stream().sorted((a,b)->a.getValue().getCount()-b.getValue().getCount()).limit(evictCount).forEach(entry->cache.remove(entry.getKey()));

return;

}

cache.put(key, new CacheItem(value, new AtomicInteger()));

}

public V get(K key){

CacheItem item = cache.get(key);

if(item != null){

item.hit();

hitCount.incrementAndGet();

return item.getValue();

}

notHitCount.incrementAndGet();

return null;

}

private static class CacheItem{

private V value;

private AtomicInteger count;

public CacheItem(V value, AtomicInteger count) {

this.value = value;

this.count = count;

}

public void hit(){

this.count.incrementAndGet();

}

public V getValue() {

return value;

}

public int getCount() {

return count.get();

}

}

public static void main(String[] args) {

ConcurrentLRUCache cache = new ConcurrentLRUCache<>(5);

for(int i=0; i<9; i++){

cache.put(i, i);

if(i%2==0){

for(int j=0; j

cache.get(i);

}

}

}

System.out.println(cache.getStatus());

System.out.println(cache.getKeyAndHitCount());

}

}

运行代码控制台输出如下:

最大缓存数量: 5

当前缓存数量: 5

驱逐缓存次数: 2

命中缓存次数: 30

未命中缓存次数: 0

缓存命中比例: 100.0 %

1810

268

346

424

502

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值