using ThreadLocal to cache data in request scope

/**
 * aim to cache the data that's accessed frequently and costly.
 * @param <K>
 * @param <V>
 */
public interface Cache<K,V> {

    V get(K k);

    void put(K k, V v);

    void clean();

    int size();
}
/**
 *this class is an implementor from Cache.and It cache data in thread local.
 * @see Cache
 * @see ThreadLocal
 */
public class ThreadLocalCache<K,V> implements Cache<K,V>{

    private ThreadLocal<Map<K,V>>  threadLocal = new ThreadLocal<>();

    public ThreadLocal<Map<K, V>> getThreadLocal() {
        return threadLocal;
    }

    public void setThreadLocal(ThreadLocal<Map<K, V>> threadLocal) {
        this.threadLocal = threadLocal;
    }

    private Map<K, V> getThreadLocalMap(){
        Map<K, V> map = getThreadLocal().get();
        if (map == null){
            map = new HashMap();
            getThreadLocal().set(map);
        }
        return map;
    }

    protected void cleanThreadLocal(){
        Map<K, V> map = getThreadLocal().get();
        if (map != null)
            map.clear();
        getThreadLocal().remove();
    }

    private int sizeThreadLocal(){
        Map<K, V> map = threadLocal.get();
        return map == null ? 0 : map.size();
    }

    @Override
    public V get(K k) {
        return getThreadLocalMap().get(k);
    }

    @Override
    public void put(K k, V v) {
        getThreadLocalMap().put(k,v);
    }

    @Override
    public void clean() {
        cleanThreadLocal();
    }

    @Override
    public int size() {
        return sizeThreadLocal();
    }
}
/**
 *  this class is to create a threadLocal through Factory.
 *  @see ThreadLocalFactory
 *  @see com.pretang.cloud.service.agent.AgentRpcService
 */
public class FactoryThreadLocalCache<K,V> extends ThreadLocalCache<K,V> {

    public FactoryThreadLocalCache() {
        super();
        super.setThreadLocal(ThreadLocalFactory.getThreadLocal());
    }
}
/**
 *  this class is a building ThreadLocal factory. And to manage the lifetime of the threadLocal.
 *  @see FactoryThreadLocalCache
 */
public abstract class ThreadLocalFactory {

    // a sharing ThreadLocal in heap.
    private static final ThreadLocal threadLocal = new ThreadLocal();

    /**
     *  get a threadLocal instance.
     * @return
     */
    public static ThreadLocal getThreadLocal(){
        return threadLocal;
    }

    /**
     * clean the threadLocal
     */
    public static void cleanThreadLocal(){
        Object obj = threadLocal.get();
        if (null != obj && obj instanceof Collection)
            ((Collection) obj).clear();
        threadLocal.remove();
    }
}
@Component
@WebFilter
public class CustomerFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        filterChain.doFilter(servletRequest,servletResponse);
        // clean the variables in threads for a request
        ThreadLocalFactory.cleanThreadLocal();
    }

    @Override
    public void destroy() {

    }
}
    private static final Cache<Integer, AgentDto> agentDtoCache = new FactoryThreadLocalCache<>();
    private static final Cache<Integer, AgentUser> agentUserCache = new FactoryThreadLocalCache<>();

猜你喜欢

转载自blog.51cto.com/881206524/2104969
今日推荐