All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dream.system.cache.MemoryCache Maven / Gradle / Ivy

package com.dream.system.cache;

import com.dream.system.config.MappedStatement;
import com.dream.util.common.ObjectUtil;
import com.dream.util.exception.DreamRunTimeException;

import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

public class MemoryCache implements Cache {
    private final int limit;
    private final double rate;
    private final AtomicBoolean canDelete = new AtomicBoolean(true);
    protected Map> tableMap = new ConcurrentHashMap<>(512);
    protected Map> indexMap = new ConcurrentHashMap<>();

    public MemoryCache() {
        this(100, 0.25);
    }

    public MemoryCache(int limit, double rate) {
        if (limit <= 0) {
            throw new DreamRunTimeException("参数limit必须大于0");
        }
        if (rate <= 0 || rate > 1) {
            throw new DreamRunTimeException("参数rate介于0-1之间");
        }
        this.limit = limit;
        this.rate = rate;
    }

    @Override
    public void put(MappedStatement mappedStatement, Object value) {
        CacheKey uniqueKey = mappedStatement.getUniqueKey();
        Set tableSet = mappedStatement.getTableSet();
        if (uniqueKey != null && !ObjectUtil.isNull(tableSet)) {
            CacheKey methodKey = mappedStatement.getMethodKey();
            for (String table : tableSet) {
                Set cacheKeySet = tableMap.get(table);
                if (cacheKeySet == null) {
                    synchronized (this) {
                        cacheKeySet = tableMap.get(table);
                        if (cacheKeySet == null) {
                            cacheKeySet = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
                            tableMap.put(table, cacheKeySet);
                        }
                    }
                }
                cacheKeySet.add(methodKey);
            }
            Map keyMap = indexMap.get(methodKey);
            if (keyMap == null) {
                synchronized (this) {
                    keyMap = indexMap.get(methodKey);
                    if (keyMap == null) {
                        keyMap = new ConcurrentHashMap<>(limit);
                        indexMap.put(methodKey, keyMap);
                    }
                }
            } else if (keyMap.size() > limit) {
                if (canDelete.compareAndSet(true, false)) {
                    Map finalMap = keyMap;
                    Iterator> iterator = finalMap.entrySet().iterator();
                    while (iterator.hasNext()) {
                        iterator.next();
                        double random = Math.random();
                        if (random <= rate) {
                            iterator.remove();
                        }
                    }
                    canDelete.set(true);
                }
            }
            keyMap.put(uniqueKey, value);
        }
    }

    @Override
    public Object get(MappedStatement mappedStatement) {
        CacheKey uniqueKey = mappedStatement.getUniqueKey();
        if (uniqueKey != null) {
            CacheKey methodKey = mappedStatement.getMethodKey();
            Map keyMap = indexMap.get(methodKey);
            if (keyMap != null) {
                return keyMap.get(uniqueKey);
            }
        }
        return null;
    }

    @Override
    public void remove(MappedStatement mappedStatement) {
        Set tableSet = mappedStatement.getTableSet();
        if (!ObjectUtil.isNull(tableSet)) {
            for (String table : tableSet) {
                Set cacheKeySet = tableMap.get(table);
                if (!ObjectUtil.isNull(cacheKeySet)) {
                    for (CacheKey cacheKey : cacheKeySet) {
                        Map keyMap = indexMap.remove(cacheKey);
                        if (!ObjectUtil.isNull(keyMap)) {
                            keyMap.clear();
                        }
                    }
                    cacheKeySet.clear();
                }
            }
        }
    }

    @Override
    public void clear() {
        for (Set cacheKeySet : tableMap.values()) {
            cacheKeySet.clear();
        }
        tableMap.clear();
        for (Map cacheKeyMap : indexMap.values()) {
            cacheKeyMap.clear();
        }
        indexMap.clear();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy