玩家缓存清理线程优化
parent
2b8bd96c28
commit
9c8b2e2aa7
|
|
@ -130,6 +130,12 @@ public class TimeUtils {
|
|||
return _calendar.getTimeInMillis();
|
||||
}
|
||||
|
||||
public static Date stringToDate(String dateString) {
|
||||
DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(ymdhms_Format_new);
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(dateString, FORMATTER);
|
||||
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间戳字符串yyyyMMDDHHmmss
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@ public class OnlineUserManager {
|
|||
|
||||
public static Map<Integer,Integer> tokenMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void checkOnline(){
|
||||
UserManager.adjustCacheBasedOnCurrentLoad();
|
||||
}
|
||||
|
||||
// public static void checkOnline(){
|
||||
// UserManager.adjustCacheBasedOnCurrentLoad();
|
||||
// }
|
||||
|
||||
public static void userOffline(int uid) {
|
||||
if(sessionMap.containsKey(uid)){
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ public class UserManager {
|
|||
// 玩家数据缓存
|
||||
private static final int maxMemoryLimit = 1000; // 最大内存限制,实际应由您的服务器规格决定
|
||||
private static final long LIVE_TIME = 60 * 60 * 1000L;// 离线玩家缓存保留时间(毫秒)
|
||||
private static final DynamicLRUCache<Integer, User> userMap = new DynamicLRUCache<>(100, LIVE_TIME);
|
||||
private static final DynamicLRUCache<Integer, User> userMap = new DynamicLRUCache<>(600, LIVE_TIME);
|
||||
private static final AtomicInteger login_f_num = new AtomicInteger(0);//登陆计数
|
||||
|
||||
|
||||
|
|
@ -72,6 +72,7 @@ public class UserManager {
|
|||
// 这个方法可能由定时任务或某种监控服务调用
|
||||
public static void adjustCacheBasedOnCurrentLoad() {
|
||||
// 调用缓存的调整方法来根据在线玩家数量调整缓存大小
|
||||
Thread.currentThread().setName("user_cache_clean");
|
||||
userMap.shrinkToFit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.ljsd.IManager;
|
|||
import com.ljsd.jieling.logic.dao.UserManager;
|
||||
import com.ljsd.jieling.thread.task.*;
|
||||
import com.ljsd.jieling.util.ConfigurableApplicationContextManager;
|
||||
import com.ljsd.jieling.util.TaskKit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import util.TimeUtils;
|
||||
|
|
@ -32,7 +33,7 @@ public class ThreadManager implements IManager {
|
|||
|
||||
public void init() {
|
||||
|
||||
mongoDataHandlerTask = ConfigurableApplicationContextManager.getBean(MongoDataHandlerTask.class);
|
||||
mongoDataHandlerTask = ConfigurableApplicationContextManager.getBean(MongoDataHandlerTask.class);
|
||||
// dataReportTask = ConfigurableApplicationContextManager.getBean(DataReportTask.class);
|
||||
itemLogTask = ConfigurableApplicationContextManager.getBean(ItemLogTask.class);
|
||||
|
||||
|
|
@ -118,9 +119,9 @@ public class ThreadManager implements IManager {
|
|||
// 每秒钟任务
|
||||
scheduledFutureSets.add(scheduledExecutor.scheduleAtFixedRate(new SecondsTask(), delayForMinute + 10, 1, TimeUnit.SECONDS));
|
||||
// 战力任务
|
||||
scheduledFutureSets.add(scheduledExecutor.scheduleAtFixedRate(new ForceRankTask(), 60,5, TimeUnit.SECONDS));
|
||||
TaskKit.scheduleAtFixedRate(new ForceRankTask(), 60,5, TimeUnit.SECONDS);
|
||||
// 每小时减容用户缓存
|
||||
scheduledFutureSets.add(scheduledExecutor.scheduleAtFixedRate(UserManager::adjustCacheBasedOnCurrentLoad, 10, 60, TimeUnit.MINUTES));
|
||||
TaskKit.scheduleAtFixedRate(UserManager::adjustCacheBasedOnCurrentLoad, 3, 1, TimeUnit.HOURS);
|
||||
// 定时重启线程池
|
||||
scheduledFutureSets.add(scheduledExecutor.scheduleAtFixedRate(new Thread(() -> {
|
||||
long lastMilis = System.currentTimeMillis();
|
||||
|
|
|
|||
|
|
@ -100,7 +100,13 @@ public class DynamicLRUCache<K, V> {
|
|||
if (cache.size() < maxSize / 2 && maxSize > 100) {
|
||||
maxSize /= 2; // 缩小缓存容量
|
||||
}
|
||||
cache.entrySet().removeIf(entry -> isEntryExpired(entry.getValue()));
|
||||
Iterator<Map.Entry<K, TimedCacheEntry<V>>> iterator = cache.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<K, TimedCacheEntry<V>> entry = iterator.next();
|
||||
if (isEntryExpired(entry.getValue())) {
|
||||
iterator.remove(); // 使用迭代器来安全移除条目
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,195 +1,204 @@
|
|||
package com.ljsd.jieling.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import util.TimeUtils;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*
|
||||
* @author <a href="mailto:biezhi.me@gmail.com" target="_blank">biezhi</a>
|
||||
* @since 1.0
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class TaskKit {
|
||||
//
|
||||
// private static final Logger LOGGER = LoggerFactory.getLogger(TaskKit.class);
|
||||
//
|
||||
// private static ScheduledThreadPoolExecutor taskScheduler = new ScheduledThreadPoolExecutor(getBestPoolSize());
|
||||
// private static List<Timer> timerList = new ArrayList<>();
|
||||
//
|
||||
// /**
|
||||
// * 立即启动,并以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param periodSeconds 每次执行任务的间隔时间(单位秒)
|
||||
// */
|
||||
// public static ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long periodSeconds) {
|
||||
// return scheduleAtFixedRate(task, 0, periodSeconds, TimeUnit.SECONDS);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 在指定的延时之后开始以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param initialDelay 首次执行任务的延时时间
|
||||
// * @param period 每次执行任务的间隔时间(单位秒)
|
||||
// * @param unit 时间单位
|
||||
// */
|
||||
// public static ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
|
||||
// return taskScheduler.scheduleAtFixedRate(task, initialDelay, period, unit);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 在指定的时间点开始以固定的频率运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param startTime 首次运行的时间点,支持 "yyyy-MM-dd HH:mm:ss" 格式
|
||||
// * @param period 每次执行任务的间隔时间
|
||||
// * @param unit 时间单位
|
||||
// */
|
||||
// public static void scheduleAtFixedRate(Runnable task, String startTime, long period, TimeUnit unit) throws ParseException {
|
||||
// Date dt = TimeUtils.dateFormat(startTime);
|
||||
// scheduleAtFixedRate(task, dt, period, unit);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 在指定的时间点开始以固定的频率运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param startTime 首次运行的时间点
|
||||
// * @param period 每次执行任务的间隔时间
|
||||
// * @param unit 时间单位
|
||||
// */
|
||||
// public static void scheduleAtFixedRate(final Runnable task, Date startTime, final long period, final TimeUnit unit) {
|
||||
// final Timer timer = new Timer();
|
||||
// timer.schedule(new TimerTask() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// taskScheduler.scheduleAtFixedRate(task, 0, period, unit);
|
||||
// timer.cancel();
|
||||
// timerList.remove(timer);
|
||||
// }
|
||||
// }, startTime);
|
||||
// timerList.add(timer);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 在指定的时间点开始一次任务。
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param startTime 首次运行的时间点
|
||||
// * @param unit 时间单位
|
||||
// */
|
||||
// public static void scheduleOne(final Runnable task, long startTime, final TimeUnit unit) {
|
||||
// taskScheduler.schedule(task,startTime,unit);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 立即启动,两次任务间保持固定的时间间隔
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param periodSeconds 两次任务的间隔时间(单位秒)
|
||||
// */
|
||||
// public static ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long periodSeconds) {
|
||||
// return scheduleWithFixedDelay(task, 0, periodSeconds, TimeUnit.SECONDS);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 在指定的延时之后启动,两次任务间保持固定的时间间隔
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param initialDelay 首次执行任务的延时时间
|
||||
// * @param period 两次任务的间隔时间(单位秒)
|
||||
// * @param unit 时间单位
|
||||
// */
|
||||
// public static ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long period, TimeUnit unit) {
|
||||
// return taskScheduler.scheduleWithFixedDelay(task, initialDelay, period, unit);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 在指定的时间点启动,两次任务间保持固定的时间间隔
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param startTime 首次运行的时间点,支持 "yyyy-MM-dd HH:mm:ss" 格式
|
||||
// * @param period 两次任务的间隔时间
|
||||
// * @param unit 时间单位
|
||||
// */
|
||||
// public static void scheduleWithFixedDelay(Runnable task, String startTime, long period, TimeUnit unit) throws ParseException {
|
||||
// Date dt = TimeUtils.dateFormat(startTime);
|
||||
// scheduleWithFixedDelay(task, dt, period, unit);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 在指定的时间点启动,两次任务间保持固定的时间间隔
|
||||
// * @param task 具体待执行的任务
|
||||
// * @param startTime 首次运行的时间点
|
||||
// * @param period 两次任务的间隔时间
|
||||
// * @param unit 时间单位
|
||||
// */
|
||||
// public static void scheduleWithFixedDelay(final Runnable task, Date startTime, final long period, final TimeUnit unit) {
|
||||
// final Timer timer = new Timer();
|
||||
// timer.schedule(new TimerTask() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// taskScheduler.scheduleWithFixedDelay(task, 0, period, unit);
|
||||
// timer.cancel();
|
||||
// timerList.remove(timer);
|
||||
// }
|
||||
// }, startTime);
|
||||
// timerList.add(timer);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 调整线程池大小
|
||||
// * @param threadPoolSize
|
||||
// */
|
||||
// public static void resizeThreadPool(int threadPoolSize) {
|
||||
// taskScheduler.setCorePoolSize(threadPoolSize);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 返回定时任务线程池,可做更高级的应用
|
||||
// * @return
|
||||
// */
|
||||
// public static ScheduledThreadPoolExecutor getTaskScheduler() {
|
||||
// return taskScheduler;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 关闭定时任务服务
|
||||
// * <p>系统关闭时可调用此方法终止正在执行的定时任务,一旦关闭后不允许再向线程池中添加任务,否则会报RejectedExecutionException异常</p>
|
||||
// */
|
||||
// public static void depose() {
|
||||
// int timerNum = timerList.size();
|
||||
// //清除Timer
|
||||
// synchronized (timerList) {
|
||||
// for (Timer t: timerList)
|
||||
// t.cancel();
|
||||
// timerList.clear();
|
||||
// }
|
||||
//
|
||||
// List<Runnable> awaitingExecution = taskScheduler.shutdownNow();
|
||||
// LOGGER.info("Tasks stopping. Tasks awaiting execution: {}", timerNum + awaitingExecution.size());
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 重启动定时任务服务
|
||||
// */
|
||||
// public static void reset() {
|
||||
// depose();
|
||||
// taskScheduler = new ScheduledThreadPoolExecutor(getBestPoolSize());
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 根据 Java 虚拟机可用处理器数目返回最佳的线程数。<br>
|
||||
// * 最佳的线程数 = CPU可用核心数 / (1 - 阻塞系数),其中阻塞系数这里设为0.9
|
||||
// */
|
||||
// private static int getBestPoolSize() {
|
||||
// int num = 0;
|
||||
// try {
|
||||
// // JVM可用处理器的个数
|
||||
// final int cores = Runtime.getRuntime().availableProcessors();
|
||||
// // 最佳的线程数 = CPU可用核心数 / (1 - 阻塞系数)
|
||||
// // TODO 阻塞系数是不是需要有个setter方法能让使用者自由设置呢?
|
||||
// num = (int)(cores / (1 - 0.9));
|
||||
// if (num > 8) {
|
||||
// num = 8;
|
||||
// }
|
||||
// }
|
||||
// catch (Throwable e) {
|
||||
// // 异常发生时姑且返回10个任务线程池
|
||||
// num = 5;
|
||||
// }
|
||||
// LOGGER.info("定时器线程启动,线程数量:{}",num);
|
||||
// return num;
|
||||
// }
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskKit.class);
|
||||
|
||||
private static ScheduledThreadPoolExecutor taskScheduler = new ScheduledThreadPoolExecutor(getBestPoolSize());
|
||||
private static List<Timer> timerList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 立即启动,并以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
* @param task 具体待执行的任务
|
||||
* @param periodSeconds 每次执行任务的间隔时间(单位秒)
|
||||
*/
|
||||
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long periodSeconds) {
|
||||
return scheduleAtFixedRate(task, 0, periodSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的延时之后开始以固定的频率来运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
* @param task 具体待执行的任务
|
||||
* @param initialDelay 首次执行任务的延时时间
|
||||
* @param period 每次执行任务的间隔时间(单位秒)
|
||||
* @param unit 时间单位
|
||||
*/
|
||||
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
|
||||
return taskScheduler.scheduleAtFixedRate(task, initialDelay, period, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的时间点开始以固定的频率运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
* @param task 具体待执行的任务
|
||||
* @param startTime 首次运行的时间点,支持 "yyyy-MM-dd HH:mm:ss" 格式
|
||||
* @param period 每次执行任务的间隔时间
|
||||
* @param unit 时间单位
|
||||
*/
|
||||
public static void scheduleAtFixedRate(Runnable task, String startTime, long period, TimeUnit unit) {
|
||||
Date dt = TimeUtils.stringToDate(startTime);
|
||||
scheduleAtFixedRate(task, dt, period, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的时间点开始以固定的频率运行任务。后续任务的启动时间不受前次任务延时影响。
|
||||
* @param task 具体待执行的任务
|
||||
* @param startTime 首次运行的时间点
|
||||
* @param period 每次执行任务的间隔时间
|
||||
* @param unit 时间单位
|
||||
*/
|
||||
public static void scheduleAtFixedRate(final Runnable task, Date startTime, final long period, final TimeUnit unit) {
|
||||
final Timer timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
taskScheduler.scheduleAtFixedRate(task, 0, period, unit);
|
||||
timer.cancel();
|
||||
timerList.remove(timer);
|
||||
}
|
||||
}, startTime);
|
||||
timerList.add(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的时间点开始一次任务。
|
||||
* @param task 具体待执行的任务
|
||||
* @param startTime 首次运行的时间点
|
||||
* @param unit 时间单位
|
||||
*/
|
||||
public static void scheduleOne(final Runnable task, long startTime, final TimeUnit unit) {
|
||||
taskScheduler.schedule(task,startTime,unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即启动,两次任务间保持固定的时间间隔
|
||||
* @param task 具体待执行的任务
|
||||
* @param periodSeconds 两次任务的间隔时间(单位秒)
|
||||
*/
|
||||
public static ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long periodSeconds) {
|
||||
return scheduleWithFixedDelay(task, 0, periodSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的延时之后启动,两次任务间保持固定的时间间隔
|
||||
* @param task 具体待执行的任务
|
||||
* @param initialDelay 首次执行任务的延时时间
|
||||
* @param period 两次任务的间隔时间(单位秒)
|
||||
* @param unit 时间单位
|
||||
*/
|
||||
public static ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long period, TimeUnit unit) {
|
||||
return taskScheduler.scheduleWithFixedDelay(task, initialDelay, period, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的时间点启动,两次任务间保持固定的时间间隔
|
||||
* @param task 具体待执行的任务
|
||||
* @param startTime 首次运行的时间点,支持 "yyyy-MM-dd HH:mm:ss" 格式
|
||||
* @param period 两次任务的间隔时间
|
||||
* @param unit 时间单位
|
||||
*/
|
||||
public static void scheduleWithFixedDelay(Runnable task, String startTime, long period, TimeUnit unit) throws ParseException {
|
||||
Date dt = TimeUtils.stringToDate(startTime);
|
||||
scheduleWithFixedDelay(task, dt, period, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定的时间点启动,两次任务间保持固定的时间间隔
|
||||
* @param task 具体待执行的任务
|
||||
* @param startTime 首次运行的时间点
|
||||
* @param period 两次任务的间隔时间
|
||||
* @param unit 时间单位
|
||||
*/
|
||||
public static void scheduleWithFixedDelay(final Runnable task, Date startTime, final long period, final TimeUnit unit) {
|
||||
final Timer timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
taskScheduler.scheduleWithFixedDelay(task, 0, period, unit);
|
||||
timer.cancel();
|
||||
timerList.remove(timer);
|
||||
}
|
||||
}, startTime);
|
||||
timerList.add(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整线程池大小
|
||||
* @param threadPoolSize
|
||||
*/
|
||||
public static void resizeThreadPool(int threadPoolSize) {
|
||||
taskScheduler.setCorePoolSize(threadPoolSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回定时任务线程池,可做更高级的应用
|
||||
* @return
|
||||
*/
|
||||
public static ScheduledThreadPoolExecutor getTaskScheduler() {
|
||||
return taskScheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭定时任务服务
|
||||
* <p>系统关闭时可调用此方法终止正在执行的定时任务,一旦关闭后不允许再向线程池中添加任务,否则会报RejectedExecutionException异常</p>
|
||||
*/
|
||||
public static void depose() {
|
||||
int timerNum = timerList.size();
|
||||
//清除Timer
|
||||
synchronized (timerList) {
|
||||
for (Timer t: timerList)
|
||||
t.cancel();
|
||||
timerList.clear();
|
||||
}
|
||||
|
||||
List<Runnable> awaitingExecution = taskScheduler.shutdownNow();
|
||||
LOGGER.info("Tasks stopping. Tasks awaiting execution: {}", timerNum + awaitingExecution.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 重启动定时任务服务
|
||||
*/
|
||||
public static void reset() {
|
||||
depose();
|
||||
taskScheduler = new ScheduledThreadPoolExecutor(getBestPoolSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Java 虚拟机可用处理器数目返回最佳的线程数。<br>
|
||||
* 最佳的线程数 = CPU可用核心数 / (1 - 阻塞系数),其中阻塞系数这里设为0.9
|
||||
*/
|
||||
private static int getBestPoolSize() {
|
||||
int num = 0;
|
||||
try {
|
||||
// JVM可用处理器的个数
|
||||
final int cores = Runtime.getRuntime().availableProcessors();
|
||||
// 最佳的线程数 = CPU可用核心数 / (1 - 阻塞系数)
|
||||
// TODO 阻塞系数是不是需要有个setter方法能让使用者自由设置呢?
|
||||
num = (int)(cores / (1 - 0.9));
|
||||
if (num > 8) {
|
||||
num = 8;
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
// 异常发生时姑且返回10个任务线程池
|
||||
num = 5;
|
||||
}
|
||||
LOGGER.info("定时器线程启动,线程数量:{}",num);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue