current position:Home>Implementing a caching mechanism using soft references

Implementing a caching mechanism using soft references

2022-08-06 17:39:04My2538772270

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情

“读多写少”Is a feature of most projects.例如“购物”,People always see more(读)、买的人少(写).因此,如果能减少“读”请求的次数,Can reduce the pressure from the server.The most direct reduction“读”The number of requests is to use the cache.

Soft references and strong reference

For the same read requests,Only need to visit for the first time from the database query data,And the query to save the data to the cache,After can be directly in the cache access query request,从而减少对数据库的访问次数.

This kind of life we often see,Such as access to aapp某商品,For the first time in loads a meet,Continue to click is directly behind the appear.

image.png

根据目前所学知识,我们可以使用 HashMap In the memory level cache function.例如,可以使用一个 HashMap Object to save the client the result of the first request,之后,When the client a read request again,就从 HashMap Object traversal query,如果 HashMap Is saved in the client to query data,就直接返回,Otherwise the queries the database by again,并将查询结果保存到 HashMap 中.

This cache design idea is very simple,但也存在一个问题:HashMap When cached data is cleared?

Memory capacity is limited,If the endless to HashMap 缓存数据,On the memory capacity will obviously pressure.一种解决方案就是使用 JVM 提供的软引用,实现对 HashMap Cache data selection strategy.

Is the most commonly used in the development of strong reference,例如 Goods goods = new Goods() Creates a strong reference object“goods”.As long as the strong reference to the scope of the no end,Or has not been developer manually set to null,So strong reference object will always exist in the JVM 内存中.

而 JVM Provide soft references is flexible:当 JVM The memory is enough,GC Treatment of soft references and strong reference is the same;但当 JVM 的内存不足时,GC Will go to take the initiative to recycle soft reference object.可见,Very suitable for cached objects in soft references.Soft references need JDK 提供的 java.lang.ref.SoftReference 类来实现.

项目

使用idea创建一个maven项目

结构如下

image.png

首先对GoodEntity class to write.

要求,goods有属性id,nameAnd writing hisgetset方法,And have no arguments constructor refs.

这里代码省略.

然后我们在goodbase里面编写代码,模拟一个数据库

里面主要有hashmap,并且通过get方法,得到该hashmap

public class GoodsBase {

    private static Map<String, Goods> base = new HashMap<>();

    public static Map<String, Goods> getBase() {
        return base;
    }
}
复制代码

然后书写goodscache缓存类

Here we need to contact a new keywordvolatile

  1. 使用volatile关键字会强制将修改的值立即写入主存;
  2. 使用volatile关键字的话,When the main thread to modify,会导致RunThread的工作内存中isRunningVariable cache value becomes invalid.
  3. 由于RunThread的工作内存中缓存变量isRunning缓存无效,So would read from the main memory againisRunning变量值.

在mapInside through generic cache object storage in soft references(map里面)

代码如下:

public class GoodsCache {

    private volatile static GoodsCache goodsCache;

    public GoodsCache(){
        this.cache = new HashMap<>();
    }

    public static GoodsCache getGoodsCache() {
        if(goodsCache == null) {
            synchronized (GoodsCache.class){
                if(goodsCache == null){
                    goodsCache = new GoodsCache();
                }
            }
        }
        return goodsCache;
    }

    // Will be cached objects stored in a soft reference
    private Map<String, SoftReference<Goods>> cache;

    // 根据id存储缓存Goods对象
    public void setCache(Goods goods) {
        cache.put(goods.getId(), new SoftReference<Goods>(goods));
        System.out.println("Add data to the cache success");
    }

    // 根据id从缓存中获取对象
    public Goods getCache(String id) {
        // 根据id,Access to the cache object soft references
        SoftReference<Goods> softRef = cache.get(id);
        return softRef == null ? null : softRef.get();
    }

    public void delCache(String id) {
        cache.remove(id);
        System.out.println("Delete data from the cache success");
    }
}
复制代码

接下来我们书写goodsservice代码,To simulate the database to add and delete,But we are throughid来进行

public class GoodsService {

    GoodsCache goodsCache = GoodsCache.getGoodsCache();

    public Goods getById(String id){
        if(goodsCache.getCache(id) == null){
            Goods goods = GoodsBase.getBase().get(id);
            goodsCache.setCache(goods);
            System.out.println("从数据库读取数据");
            System.out.println(goods.getName());
            return goods;
        }
        System.out.println(goodsCache.getCache(id).getName());
        return goodsCache.getCache(id);
    }

    public void add(Goods goods){
        goodsCache.setCache(goods);
        GoodsBase.getBase().put(goods.getId(), goods);
        System.out.println("添加数据到数据库");
    }

    public void deleteById(String id){
        if(goodsCache.getCache(id) != null){
            goodsCache.delCache(id);
        }
        GoodsBase.getBase().remove(id);
    }
}
复制代码

Finally, we writetest文件

image.png

运行结果

image.png

You can see the second run goodsService.getById("1"); Read directly from the cache data,也可以看出,With a soft reference implementation actually caching mechanism,Read the object is the same.

copyright notice
author[My2538772270],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/218/202208061716152588.html

Random recommended