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.


根据目前所学知识,我们可以使用 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 类来实现.





首先对GoodEntity class to write.

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




public class GoodsBase {

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

    public static Map<String, Goods> getBase() {
        return base;


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) {
        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);
            return goods;
        return goodsCache.getCache(id);

    public void add(Goods goods){
        GoodsBase.getBase().put(goods.getId(), goods);

    public void deleteById(String id){
        if(goodsCache.getCache(id) != null){

Finally, we writetest文件




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.

Random recommended