欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java 手写 jvm高性能缓存

程序员文章站 2022-07-09 21:18:19
java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置 缓存接口 package com.ws.commons.cache; public interface ICache { void expire(String key, int timeOutSecond); void leftP ......

java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置

缓存接口

package com.ws.commons.cache;

public interface icache {

    void expire(string key, int timeoutsecond);

    void leftpush(string key, object value);

    void rightpush(string key, object value);

    void rightpush(string key, object value, int timeoutsecond);

    <t> t rightpop(string key);

    <t> t leftpop(string key);

    void put(string key, object value);

    void put(string key, object value, int timeoutsecond);

    boolean putifabsent(string key, object value);

    boolean putifabsent(string key, object value, int timeoutsecond);

    <t> t get(string key);

    boolean haskey(string key);

    void remove(string key);

    <t> t removeandget(string key);
}

实现类

package com.ws.commons.cache;

import java.time.localdatetime;
import java.time.format.datetimeformatter;
import java.util.arraylist;
import java.util.collections;
import java.util.iterator;
import java.util.linkedhashmap;
import java.util.list;
import java.util.map;
import java.util.map.entry;
import java.util.concurrent.concurrentlinkeddeque;
import java.util.concurrent.executorservice;
import java.util.concurrent.executors;
import java.util.concurrent.atomic.atomicinteger;

import com.ws.commons.tool.threadtool;

/**
 * 本地高性能缓存
 * 
 * @author 尘无尘
 *
 */
public class localcache implements icache {

    private static localcache staticinstance;

    public static localcache instance() {
        if (staticinstance != null) {
            return staticinstance;
        } else {
            synchronized (localcache.class) {
                if (staticinstance != null) {
                    return staticinstance;
                }
                staticinstance = new localcache();
                return staticinstance;
            }
        }
    }

    private localcache() {
    }

    /**
     * 缓存实例
     */
    private static final map<string, object> instance = collections.synchronizedmap(new linkedhashmap<>());

    /**
     * 缓存key 存储时间记录
     */
    private static final map<string, long> key_time_instance = collections.synchronizedmap(new linkedhashmap<>());

    /**
     * 时间格式化对象
     */
    public static final datetimeformatter yyyymmddhhmmss_fmt = datetimeformatter.ofpattern("yyyymmddhhmmss");

    /**
     * 存储最大数据数量,超出该数据量时,删除最新存储的数据
     */
    private static final int maxcount = 10000;

    /**
     * 清理缓存线程,防止频繁的缓存清理 创建线程消耗性能
     */
    private static final executorservice thread_pool = executors.newcachedthreadpool();

    /**
     * 清理缓存时线程做的标记
     */
    private static final atomicinteger tream_cache_flag = new atomicinteger(0);

    /**
     * 缓存清理 轮询一圈等待时长
     */
    private static final int trim_interim = 2000;

    /**
     * 队列存储,在末尾添加元素
     * 
     * @param key
     * @param value
     * @param outsecond 保存时间(秒),超出时间,被清除
     */
    @suppresswarnings("unchecked")
    @override
    public void rightpush(string key, object value, int outsecond) {
        concurrentlinkeddeque<object> linklist = (concurrentlinkeddeque<object>) instance.get(key);
        if (linklist == null) {
            linklist = new concurrentlinkeddeque<>();
            instance.put(key, linklist);
        }
        key_time_instance.put(key,
                long.parselong(localdatetime.now().plusseconds(outsecond).format(yyyymmddhhmmss_fmt)));
        linklist.offer(value);
        localcache.streaminstance();
    }

    /**
     * 队列存储,在末尾添加元素
     * 
     * @param key
     * @param value
     */
    @suppresswarnings("unchecked")
    @override
    public void rightpush(string key, object value) {
        concurrentlinkeddeque<object> linklist = (concurrentlinkeddeque<object>) instance.get(key);
        if (linklist == null) {
            linklist = new concurrentlinkeddeque<>();
            instance.putifabsent(key, linklist);
        }
        linklist.offer(value);
        localcache.streaminstance();
    }

    /**
     * 队列存储,在开头添加元素
     * 
     * @param key
     * @param value
     */
    @suppresswarnings("unchecked")
    @override
    public void leftpush(string key, object value) {
        concurrentlinkeddeque<object> linklist = (concurrentlinkeddeque<object>) instance.get(key);
        if (linklist == null) {
            linklist = new concurrentlinkeddeque<>();
            instance.putifabsent(key, linklist);
        }
        linklist.offerfirst(value);
        localcache.streaminstance();
    }

    /**
     * 删除队列的最后一个元素
     * 
     * @param key
     * @return
     */
    @suppresswarnings("unchecked")
    @override
    public <t> t rightpop(string key) {
        concurrentlinkeddeque<object> linklist = (concurrentlinkeddeque<object>) instance.get(key);
        if (linklist == null) {
            return null;
        }
        return (t) linklist.polllast();
    }

    /**
     * 删除队列的第一个元素
     * 
     * @param key
     * @return
     */
    @suppresswarnings("unchecked")
    @override
    public <t> t leftpop(string key) {
        concurrentlinkeddeque<object> linklist = (concurrentlinkeddeque<object>) instance.get(key);
        if (linklist == null) {
            return null;
        }
        return (t) linklist.pollfirst();
    }

    /**
     * 
     * @param key
     * @param value
     */

    @override
    public void put(string key, object value) {
        instance.put(key, value);
        localcache.streaminstance();
    }

    /**
     * 
     * @param key
     * @param value
     * @param outsecond 保存时间(秒),超出时间,被清除
     */
    @override
    public void put(string key, object value, int outsecond) {
        instance.put(key, value);
        key_time_instance.put(key,
                long.parselong(localdatetime.now().plusseconds(outsecond).format(yyyymmddhhmmss_fmt)));
        localcache.streaminstance();
    }

    /**
     * 
     * @param key
     * @param value
     * @return
     */
    @override
    public boolean putifabsent(string key, object value) {
        object result = null;
        result = instance.putifabsent(key, value);
        localcache.streaminstance();
        return result == null;
    }

    /**
     * 
     * @param key
     * @param value
     * @param outsecond 保存时间(秒),超出时间,被清除
     * @return
     */
    @override
    public boolean putifabsent(string key, object value, int outtimesecond) {
        object result = null;
        result = instance.putifabsent(key, value);
        key_time_instance.putifabsent(key,
                long.parselong(localdatetime.now().plusseconds(outtimesecond).format(yyyymmddhhmmss_fmt)));
        localcache.streaminstance();
        return result == null;
    }

    /**
     * 获取缓存
     * 
     * @param key
     * @return
     */
    @suppresswarnings("unchecked")
    @override
    public <t> t get(string key) {
        t value = (t) instance.get(key);
        if (value == null) {
            return null;
        }
        if (localcache.istimeout(key)) {
            instance.remove(key);
            key_time_instance.remove(key);
            return null;
        } else {
            return value;
        }
    }

    @override
    public void expire(string key, int timeoutsecond) {
        key_time_instance.put(key,
                long.parselong(localdatetime.now().plusseconds(timeoutsecond).format(yyyymmddhhmmss_fmt)));
    }

    /**
     * 是否含有
     * 
     * @param key
     * @return
     */
    @override
    public boolean haskey(string key) {
        return instance.containskey(key);
    }

    /**
     * 删除
     * 
     * @param id
     * @return
     */
    @override
    public void remove(string key) {
        instance.remove(key);
    }

    /**
     * 删除并返回
     * 
     * @param id
     * @return
     */
    @suppresswarnings("unchecked")
    @override
    public <t> t removeandget(string key) {
        return (t) instance.remove(key);
    }

    /**
     * 整理缓存:<br>
     * 整理的缓存的线程只能一个,节约资源开销<br>
     * trim_interim<br>
     */
    private static void streaminstance() {

        if (tream_cache_flag.incrementandget() > 1) {
            return;
        }
        thread_pool.execute(() -> {
            long now = long.parselong(localdatetime.now().format(yyyymmddhhmmss_fmt));
            do {
                /*
                 * 1、超时缓存清除
                 */
                iterator<entry<string, object>> instanceit = instance.entryset().iterator();
                while (instanceit.hasnext()) {
                    string key = instanceit.next().getkey();
                    if (localcache.istimeout(key, now)) {
                        instanceit.remove();
                        key_time_instance.remove(key);
                    }
                }

                /*
                 * 2、 超容量,从首位开始清除
                 */
                if (instance.size() > maxcount) {
                    list<string> templist = new arraylist<>();
                    for (entry<string, object> en : instance.entryset()) {
                        templist.add(en.getkey());
                        if (instance.size() - templist.size() <= maxcount) {
                            templist.foreach(e -> {
                                instance.remove(e);
                                key_time_instance.remove(e);
                            });
                            break;
                        }
                    }
                }

                threadtool.sleep(trim_interim);
                now = long.valueof(localdatetime.now().format(yyyymmddhhmmss_fmt));
            } while (!instance.isempty());
            tream_cache_flag.set(0);
        });
    }

    /**
     * 判断key对比当前时间是否超时
     * 
     * @param key
     * @return
     */
    private static boolean istimeout(string key) {
        long now = long.parselong(localdatetime.now().format(yyyymmddhhmmss_fmt));
        return localcache.istimeout(key, now);
    }

    /**
     * 
     * 判断key对比now是否超时
     * 
     * @param key
     * @param now
     * @return
     */
    private static boolean istimeout(string key, long now) {
        long savetime = key_time_instance.get(key);
        return savetime == null || savetime < now;
    }
}