一歩一歩、ConcurrentHashMapでキャッシュツールクラスを実現


キャッシュツールを使用する必要がある場合が多い-(ただし、現在はキャッシュの論理を整理するために書かれた専門的なキャッシュツールがたくさんあります)
まず、ストレージツールで使用されるConcurrentHashMapを定義します(同時対応)
private volatile Map data = new ConcurrentHashMap<>(16);

キャッシュは失効自動削除機能を備えている必要がありますので、格納するオブジェクトをパッケージ化する必要があります.
@Data
    class CacheObject {
        /**
         *  
         */
        private Object value;
        /**
         * dateline( )
         */
        private long expire;

        public CacheObject() {
        }

        public boolean isExpire() {
            return System.currentTimeMillis() > expire;
        }

        public CacheObject(Object value, long expire) {
            this.value = value;
            this.expire = expire;
        }
    }

追加および取得方法の追加
データを追加するには、有効期限を考慮します.
/**
     * @param key     key
     * @param value   
     * @param expire  
     * @return
     */
    public boolean add(String key, Object value, long expire) {
        CacheObject cacheObject = new CacheObject(value, expire + System.currentTimeMillis());
        data.put(key, cacheObject);
        return true;
    }

    /**
     *  key 
     *
     * @param key  key
     * @return
     */
    public Object get(String key) {
        CacheObject cacheObject = data.get(key);
        if (Objects.isNull(cacheObject)) {
            return null;
        }
        return cacheObject.getValue();
    }

データが期限切れになったかどうかを監視するタイミングタスクが必要です
  /**
     *  
     */
    private void init() {
        ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(5);

        scheduled.scheduleWithFixedDelay(() -> {
            data.entrySet().removeIf(entry -> Objects.nonNull(entry) && entry.getValue().isExpire());
        }, 100, 100, TimeUnit.MILLISECONDS);
    }

テストコード
  public static void main(String[] args) throws InterruptedException {
        HashMapCache cache = new HashMapCache();
        cache.add("AAA", "AAA", 2000);
        cache.add("BBB", "BBB", 2000);
        cache.add("CCC", "CCC", 2000);
        cache.add("DDD", "DDD", 2000);
        System.out.println(cache.get("BBB"));
        Thread.sleep(5001);
        System.out.println(cache.get("BBB"));
    }

ごみ回収メカニズムの問題を考慮して、ソフトリファレンスにアップグレードし、メモリが爆発する前にリソースを解放し、すべてのコードは以下の通りです.
package com.milla.study.netbase.expert.memory;


import lombok.Data;

import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author milla
 */
public class HashMapCacheSoftReference {
    private volatile Map> data = new ConcurrentHashMap<>(16);

    public static void main(String[] args) throws InterruptedException {
        HashMapCacheSoftReference cache = new HashMapCacheSoftReference();
        System.out.println(cache.get("BBB"));
        Thread.sleep(5001);
        System.out.println(cache.get("BBB"));
    }

    public HashMapCacheSoftReference() {
        init();
    }

    private void init() {
        ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor(5);

        scheduled.scheduleWithFixedDelay(() -> {
            data.entrySet().removeIf(o -> Optional.ofNullable(o.getValue()).map(SoftReference::get).map(CacheObject::isExpire).orElse(false));
        }, 100, 100, TimeUnit.MILLISECONDS);
    }


    public boolean add(String key, Object value, long expire) {
        if (key == null) {
            return false;
        }
        if (Objects.isNull(value)) {
            return false;
        }
        CacheObject cacheObject = new CacheObject(value, expire + System.currentTimeMillis());
        data.put(key, new SoftReference<>(cacheObject));
        return true;
    }

    public Object get(String key) {
        SoftReference cacheObjectSoftReference = data.get(key);
        if (Objects.isNull(cacheObjectSoftReference)) {
            return null;
        }
        CacheObject cacheObject = cacheObjectSoftReference.get();
        if (Objects.isNull(cacheObject)) {
            return null;
        }
        return cacheObject.getValue();
    }


    @Data
    class CacheObject {
        /**
         *  
         */
        private Object value;
        /**
         * dateline( )
         */
        private long expire;

        public CacheObject() {
        }

        public boolean isExpire() {
            return System.currentTimeMillis() > expire;
        }

        public CacheObject(Object value, long expire) {
            this.value = value;
            this.expire = expire;
        }
    }
}

ps:優れたキャッシュツールがたくさんあり、より細かく考えられているので、大体の実現構想を知るだけでいいので、自分で車輪を作る必要はありません.
以下はguavaキャッシュの部分です
maven依存
       
        
            com.google.guava
            guava
            28.2-jre
        

テストコード
 public static void main(String[] args) throws ExecutionException {
        CacheBuilder build = CacheBuilder.newBuilder();
        // 
        LoadingCache cache = build.concurrencyLevel(8)
                // 
                .expireAfterWrite(8, TimeUnit.SECONDS)
                // 
                .refreshAfterWrite(1, TimeUnit.SECONDS)
                // 
                .initialCapacity(10)
                // 
                .removalListener(notification -> System.out.println(" "))
                // 
                .recordStats()
                // 100
                .maximumSize(100)
                // 
                .build(new CacheLoader() {
                    @Override
                    public Object load(Object key) throws Exception {
                        System.out.println(" , :" + key);
                        return UUID.randomUUID().toString();
                    }
                });

        Object o = cache.get("1111");
        System.out.println(o);
        System.out.println(cache.get("1111"));
        // 
        System.out.println(cache.stats().toString());
    }