java手写多级缓存

 

多级缓存实现类,时间有限,该类未抽取接口,目前只支持两级缓存:JVM缓存(实现 请查看上一篇:java 手写JVM高性能缓存)、redis缓存(在spring 的 redisTemplate 基础实现)

package com.ws.commons.cache;

import java.util.function.Supplier;

import com.ws.commons.tool.ThreadTool;

/**
 * 多级缓存实现
 * 
 * @author 尘无尘
 *
 */
public class MultilevelCache {

    private MultilevelCache() {
    }

    private static final ICache FIRST_LEVE_LCACHE = LocalCache.instance();
    private static ICache secondCache;

    private static final String LOCK_PREFIX = "MUILCACHE_LOCK:";

    public static synchronized void init(ICache secondCache) {
        if (MultilevelCache.secondCache == null) {
            MultilevelCache.secondCache = secondCache;
        }
    }

    public static void put(String key, Object value, int timeOutSecond) {
        FIRST_LEVE_LCACHE.put(key, value, timeOutSecond);
        if (secondCache != null) {
            secondCache.put(key, value, timeOutSecond);
        }
    }

    /**
     * 提供数据,并缓存
     * 
     * @param key
     * @param supplier
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getForload(String key, Supplier<T> supplier) {
        T data = FIRST_LEVE_LCACHE.get(key);
        if (data == null && secondCache != null) {
            data = (T) secondCache.get(key);
        }
        if (data != null) {
            return data;
        }

        synchronized (ThreadTool.buildLock(LOCK_PREFIX, key)) {
            data = FIRST_LEVE_LCACHE.get(key);
            if (data == null && secondCache != null) {
                data = (T) secondCache.get(key);
            }
            if (data != null) {
                return data;
            }

            data = supplier.get();
            if (secondCache != null) {
                secondCache.put(key, data);
            }
            FIRST_LEVE_LCACHE.put(key, data);
        }
        return data;
    }

    /**
     * 提供数据,并缓存一定的时间
     * 
     * @param key
     * @param timeOutSecond
     * @param supplier
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getForload(String key, int timeOutSecond, Supplier<T> supplier) {
        T data = FIRST_LEVE_LCACHE.get(key);
        if (data == null && secondCache != null) {
            data = (T) secondCache.get(key);
        }
        if (data != null) {
            return data;
        }
        synchronized (ThreadTool.buildLock(LOCK_PREFIX, key)) {
            data = FIRST_LEVE_LCACHE.get(key);
            if (data == null && secondCache != null) {
                data = (T) secondCache.get(key);
            }
            if (data != null) {
                return data;
            }
            data = supplier.get();
            if (secondCache != null) {
                secondCache.put(key, data, timeOutSecond);
            }
            FIRST_LEVE_LCACHE.put(key, data, timeOutSecond);
        }
        return data;
    }

    @SuppressWarnings("unchecked")
    public static <T> T removeAndGet(String key) {
        T data = null;
        if (secondCache != null) {
            data = (T) secondCache.removeAndGet(key);
        }
        T data2 = FIRST_LEVE_LCACHE.removeAndGet(key);
        if (data == null) {
            data = data2;
        }
        return data;
    }

    public static void remove(String key) {
        if (secondCache != null) {
            secondCache.remove(key);
        }
        FIRST_LEVE_LCACHE.remove(key);
    }

    @SuppressWarnings("unchecked")
    public static <T> T get(String key) {
        T data = FIRST_LEVE_LCACHE.get(key);
        if (data == null && secondCache != null) {
            data = (T) secondCache.get(key);
        }
        return data;
    }

    public static void expire(String key, int timeOutSecond) {
        FIRST_LEVE_LCACHE.expire(key, timeOutSecond);
        if (secondCache != null) {
            secondCache.expire(key, timeOutSecond);
        }
    }

}

 

redis缓存实现类

package com.walmart.cirular.interfaces.application;

import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.ws.commons.cache.ICache;

/**
 * redis 缓存实现类
 * 
 * @author 尘无尘
 *
 */
@Component
public class RedisICacheImpl implements ICache {

    @Autowired(required = false)
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void put(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public void put(String key, Object value, int timeOutSecond) {
        redisTemplate.opsForValue().set(key, value, (long) timeOutSecond, TimeUnit.SECONDS);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T get(String key) {
        T t = (T) redisTemplate.opsForValue().get(key);
        redisTemplate.delete(key);
        return t;
    }

    @Override
    public void remove(String key) {
        redisTemplate.delete(key);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T removeAndGet(String key) {
        Object obj = get(key);
        redisTemplate.delete(key);
        return (T) obj;
    }

    @Override
    public void rightPush(String key, Object value, int timeOutSecond) {
        redisTemplate.opsForList().rightPush(key, value);
        redisTemplate.expire(key, timeOutSecond, TimeUnit.SECONDS);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T rightPop(String key) {
        return (T) redisTemplate.opsForList().rightPop(key);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T leftPop(String key) {
        return (T) redisTemplate.opsForList().leftPop(key);
    }

    @Override
    public void leftPush(String key, Object value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    @Override
    public void rightPush(String key, Object value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    @Override
    public void expire(String key, int timeOutSecond) {
        redisTemplate.expire(key, timeOutSecond, TimeUnit.SECONDS);
    }

    @Override
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    @Override
    public boolean putIfAbsent(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    @Override
    public boolean putIfAbsent(String key, Object value, int timeOutSecond) {
        boolean flag = putIfAbsent(key, value);
        if (flag) {
            expire(key, timeOutSecond);
        }
        return flag;
    }

}

 

点赞