Map功能扩展——支持key过期,以及触发回调事件

        经常会有需要使用map进行缓存一些数据,并且希望缓存一定时间后自动过期移除该元素;有时候还希望移除元素的时候进行回调通知,以便执行相应的业务逻辑。

        本文提供一种扩展Map功能的实现方法,供大家参考借鉴。实现的核心逻辑是添加key的时候同时记录时间,实例化该扩展Map的时候同时启动一个线程,以200毫秒的周期扫描Map的添加记录有效时间。比较添加时间和当前时间,过期的remove掉,同时调用回调方法。

        代码实现如下:

package com.xinhui.supermap;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * Map的扩展:支持key过期,以及触发回调事件
 * 
 * @author ChenChaogui
 * @Date 2024年5月18日 下午2:52:06
 * 
 * @param <K>
 * @param <V>
 */
public abstract class BaseExpireMap<K, V> {

    ConcurrentHashMap<K, V> dataMap = null;
    //控制过期时间
    ConcurrentHashMap<K, Long> expireMap = null;

    /**
     * 
     * @param key
     * @param val
     * @param expireTime 过期时间 秒数
     * @return
     */
    public V put(K key, V val, long expireTime) {
	long time = System.currentTimeMillis() + expireTime * 1000;
	expireMap.put(key, time);
	return dataMap.put(key, val);
    }

    public V remove(K key) {
	expireMap.remove(key);
	return dataMap.remove(key);
    }

    public V get(K key) {
	return dataMap.get(key);
    }

    /**
     * 过期事件 子类实现
     * 
     * @Title: baseExpireEvent
     * @param key
     * @return: void
     */
    protected abstract void baseExpireEvent(K key, V val);

    public BaseExpireMap() {
	dataMap = new ConcurrentHashMap<K, V>();
	expireMap = new ConcurrentHashMap<K, Long>();
	// 启动监听线程
	ExpireCheckTask task = new ExpireCheckTask(dataMap, expireMap) {
	    @Override
	    protected void expireEvent(K key, V val) {
		baseExpireEvent(key, val);
	    }
	};
	task.setDaemon(false);
	task.start();
    }

    /**
     * 扫描线程 定期移除过期元素并触发过期事件
     * 
     * @author ChenChaogui
     * @Date 2024年5月18日 下午2:55:41
     *
     */
    private abstract class ExpireCheckTask extends Thread {
	ConcurrentHashMap<K, Long> expireMap = null;
	ConcurrentHashMap<K, V> dataMap = null;

	public ExpireCheckTask(ConcurrentHashMap<K, V> dataMap, ConcurrentHashMap<K, Long> expireMap) {
	    this.expireMap = expireMap;
	    this.dataMap = dataMap;
	}

	protected abstract void expireEvent(K key, V val);

	public void run() {
	    Iterator<K> it = null;
	    K key = null;
	    while (true) {
		try {
		    if (expireMap != null && !expireMap.isEmpty()) {
			it = expireMap.keySet().iterator();
			while (it.hasNext()) {
			    key = it.next();
			    if (expireMap.get(key) <= System.currentTimeMillis()) {// 元素超时
				// 触发回调
				expireEvent(key, dataMap.get(key));
				// 移除
				it.remove();
				dataMap.remove(key);
				expireMap.remove(key);
			    }
			}
		    }
		    try {
			//扫描周期200毫秒
			TimeUnit.MILLISECONDS.sleep(200);
		    } catch (InterruptedException e) {
			e.getMessage();
		    }
		} catch (Exception e) {
		    e.printStackTrace();
		}
	    }

	}
    }

}

        实现类进行回调方法的实现

package com.xinhui.supermap;

import java.time.LocalTime;

/**
 * Map的扩展:支持key过期,以及触发回调事件
 * @author ChenChaogui
 * @Date 2024年5月18日 下午2:52:31
 *
 */
public class ExpireMap extends BaseExpireMap<String, String> {

    public ExpireMap() {
	super();
    }

    /**
     * key过期触发的回调方法
     */
    @Override
    protected void baseExpireEvent(String key, String value) {
	System.out.println("触发事件==> 时间:" + LocalTime.now().toString()+", key:"+key+", value: " + value);
    }

}

        测试类

package com.xinhui.supermap;

import java.time.LocalTime;

public class ExpireMapTest {
    
    public static ExpireMap expireMap = new ExpireMap();
    
    public static void main(String[] args) {
	
	System.out.println("开始时间:" + LocalTime.now().toString());
	expireMap.put("key1", "value1", 5);//5s过期
	expireMap.put("key2", "value2", 10);//10s过期
	expireMap.put("key3", "value2", 13);//13s过期
	try {
	    //等待10秒后添加key4
	    Thread.sleep(10000l);
	} catch (InterruptedException e) {
	    e.printStackTrace();
	}
	System.out.println("添加key4时间:" + LocalTime.now().toString());
	expireMap.put("key4", "value4", 5);//5s过期
    }

}

        输出结果如下:

                开始时间:15:21:51.529
                触发事件==> 时间:15:21:56.560, key:key1, value: value1
                添加key4时间:15:22:01.549
                触发事件==> 时间:15:22:01.689, key:key2, value: value2
                触发事件==> 时间:15:22:04.660, key:key3, value: value2
                触发事件==> 时间:15:22:06.589, key:key4, value: value4

完整源代码下载:https://download.csdn.net/download/snpxchen/89363148?spm=1001.2014.3001.5501

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芯晖闲云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值