一洼绿地

Java 通用本地缓存

·2 min read

Java 通用本地缓存

简介

| 主要还是利用好 ReentrantReadWriteLock 对读写进行锁操作

代码例子


import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;

public class CacheLockTest {

    static final Map<String, Integer> expireTimeMap = new HashMap<>();
    static final Map<String, ReentrantReadWriteLock> readWriteLockMap = new HashMap<>();
    static final Map<String, Object> readWriteCacheMap = new HashMap<>();

    @Test
    public void fetchCachedTest() throws Exception {
        for (int ii=0; ii<20; ii++) {
            Thread.sleep(1000);
            System.out.println(">>>" + ii);
            fetchCached("abc", 0,  ()->{return new ArrayList<String>(){{add("aa"); add("bb");}};});
            fetchCached("abcd", 10,  ()->{return 111;});
            fetchCached("abcde", 10,  ()->{return "abc";});
        }
    }

    public Object fetchCached(String key, Integer expireSecond, Supplier<Object> supplier) {
        if (readWriteLockMap.get(key) == null) {
            readWriteLockMap.put(key, new ReentrantReadWriteLock());
        }
        return fetchCached(key, expireSecond, readWriteLockMap.get(key).readLock(), readWriteLockMap.get(key).writeLock(), supplier);
    }

    public Object fetchCached(String key, Integer expireSecond, Lock readLock, Lock writeLock, Supplier<Object> supplier) {

        // 当前时间
        int nowTime = (int)(System.currentTimeMillis()/1000);
        // 上次时间
        Integer lastTime = expireTimeMap.get(key);

        readLock.lock();
        try {
            // System.out.printf("%s , %s, %s, %s%n", key, nowTime, lastTime, expireSecond);
            if (readWriteCacheMap.get(key)!=null && lastTime!=null && (expireSecond==0 || nowTime<expireSecond+lastTime)) {
                return readWriteCacheMap.get(key);
            }
        }
        finally {
            readLock.unlock();
        }

        writeLock.lock();
        try {
            lastTime = expireTimeMap.get(key);
            if (readWriteCacheMap.get(key)!=null && lastTime!=null && (expireSecond==0 || nowTime<expireSecond+lastTime)) {
                return readWriteCacheMap.get(key);
            }
            Object cacheValue = supplier.get();
            Object oldCacheValue = readWriteCacheMap.get(key);
            if (oldCacheValue instanceof Map) {
                ((Map<?, ?>) oldCacheValue).clear();
                if (cacheValue instanceof Map) {
                    ((Map<?, ?>) oldCacheValue).putAll((Map) cacheValue);
                }
                else {
                    readWriteCacheMap.put(key, cacheValue);
                }
            }
            else if (oldCacheValue instanceof Collection) {
                ((Collection<?>) oldCacheValue).clear();
                if (cacheValue instanceof Collection) {
                    System.out.println("cacheValue > " + cacheValue);
                    ((Collection<?>) oldCacheValue).addAll((Collection) cacheValue);
                }
                else {
                    readWriteCacheMap.put(key, cacheValue);
                }
            }
            else {
                readWriteCacheMap.put(key, cacheValue);
            }
            // System.out.println(readWriteCacheMap.get(key));
            expireTimeMap.put(key, nowTime);
            // return key
            return cacheValue;
        }
        finally {
            writeLock.unlock();
        }
    }
}