You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.3 KiB
118 lines
3.3 KiB
2 years ago
|
package com.ynxbd.common.helper.common;
|
||
|
|
||
|
import lombok.extern.slf4j.Slf4j;
|
||
|
import org.slf4j.MDC;
|
||
|
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.List;
|
||
|
import java.util.Map;
|
||
|
import java.util.concurrent.ConcurrentHashMap;
|
||
|
import java.util.concurrent.Executors;
|
||
|
import java.util.concurrent.ScheduledExecutorService;
|
||
|
import java.util.concurrent.TimeUnit;
|
||
|
|
||
|
/**
|
||
|
* 排重:重复通知处理
|
||
|
*/
|
||
|
@Slf4j
|
||
|
public class RepeatKeyHelper {
|
||
|
// 默认key有效时间 30分钟
|
||
|
public final static int DEFAULT_EXPIRE_TIME = 1800;
|
||
|
|
||
|
private final Map<String, Long> KEY_MAP = new ConcurrentHashMap<>();
|
||
|
|
||
|
private ScheduledExecutorService scheduledExecutorService;
|
||
|
|
||
|
// 清理key 间隔时间 60秒
|
||
|
private Integer period = 60;
|
||
|
|
||
|
public RepeatKeyHelper() {
|
||
|
timerTask();
|
||
|
}
|
||
|
|
||
|
public RepeatKeyHelper(int period) {
|
||
|
this.period = period;
|
||
|
timerTask();
|
||
|
}
|
||
|
|
||
|
private void timerTask() {
|
||
|
log.info("创建keyList");
|
||
|
if (scheduledExecutorService != null) {
|
||
|
scheduledExecutorService.shutdownNow();
|
||
|
}
|
||
|
// 守护线程 自动清理过期key,间隔时间60秒
|
||
|
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(r -> {
|
||
|
MDC.remove("ip");
|
||
|
MDC.put("ip", "Keys守护线程");
|
||
|
|
||
|
Thread thread = Executors.defaultThreadFactory().newThread(r);
|
||
|
thread.setDaemon(true);
|
||
|
return thread;
|
||
|
});
|
||
|
|
||
|
scheduledExecutorService.scheduleWithFixedDelay(() -> {
|
||
|
MDC.remove("ip");
|
||
|
MDC.put("ip", "定时任务");
|
||
|
List<String> removeKey = new ArrayList<>();
|
||
|
for (String key : KEY_MAP.keySet()) {
|
||
|
Long value = KEY_MAP.get(key);
|
||
|
long current = System.currentTimeMillis() / 1000;
|
||
|
if (value != null && value <= current) {
|
||
|
// log.info("delete:current=" + current + ", value=" + value);
|
||
|
removeKey.add(key);
|
||
|
}
|
||
|
}
|
||
|
for (String key : removeKey) {
|
||
|
KEY_MAP.remove(key);
|
||
|
}
|
||
|
if (removeKey.size() > 0) {
|
||
|
log.info("clean {} keys, remain {} keys", removeKey.size(), KEY_MAP.size());
|
||
|
}
|
||
|
}, 10, period, TimeUnit.SECONDS);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 排重处理,是否存在key
|
||
|
*
|
||
|
* @param key key
|
||
|
* @return 吃饭
|
||
|
*/
|
||
|
public synchronized boolean isContainsKey(String key) {
|
||
|
return isContainsKey(key, DEFAULT_EXPIRE_TIME);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 排重处理,是否存在key
|
||
|
*
|
||
|
* @param key key
|
||
|
* @return 是否过期或重复
|
||
|
*/
|
||
|
public synchronized boolean isContainsKey(String key, int expire) {
|
||
|
Long value = KEY_MAP.get(key);
|
||
|
if (value != null) {
|
||
|
if (value > System.currentTimeMillis() / 1000) { // 存在且没过时
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
log.info("add key=" + key);
|
||
|
KEY_MAP.put(key, (System.currentTimeMillis() / 1000) + expire);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* key数量
|
||
|
*
|
||
|
* @return 数量
|
||
|
*/
|
||
|
public int count() {
|
||
|
return KEY_MAP.size();
|
||
|
}
|
||
|
|
||
|
public void print() {
|
||
|
for (String key : KEY_MAP.keySet()) {
|
||
|
log.info("key=" + key + ", value=" + KEY_MAP.get(key));
|
||
|
}
|
||
|
}
|
||
|
}
|