simulation-backend/src/main/java/com/hivekion/room/bean/Room.java
2025-09-17 14:59:08 +08:00

142 lines
3.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.hivekion.room.bean;
import com.hivekion.common.uuid.IdUtils;
import com.hivekion.room.func.TaskAction;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import lombok.Data;
/**
* [类的简要说明]
* <p>
* [详细描述,可选]
* <p>
*
* @author LiDongYU
* @since 2025/7/22
*/
@Data
public class Room implements AutoCloseable {
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private ScheduledFuture<?> future;
private String roomId;
private Map<Long, Map<String, TaskAction>> actionMap = new ConcurrentHashMap<>();
//线程池
private final ExecutorService actionExecutor =
new ThreadPoolExecutor(
5, 5, // corePoolSize, maximumPoolSize
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1000), // 有界队列只允许100个待执行任务
new ThreadPoolExecutor.AbortPolicy() // 超出直接抛异常
);
public Room(String roomId) {
this.roomId = roomId;
}
/**
* 剩余时间
*/
private AtomicLong duringTime = new AtomicLong(0);
private AtomicLong totalTime = new AtomicLong(0);
private int mag = 1;
//获取剩余时间
public long getDuringTime() {
return duringTime.get();
}
/**
* 启动
*
* @param time 总时间
*/
public void start(long time) {
totalTime.set(time);
startTask();
}
/**
* 停止
*/
public void stop() {
cancelTask();
}
/**
* 暂停
*/
public void pause() {
cancelTask();
}
public void resume() {
startTask();
}
/**
* 快进
*
* @param mag 放大倍数
*/
public void magChange(int mag) {
this.mag = mag;
}
// 启动定时任务
private void startTask() {
if (future == null || future.isCancelled()) {
future = scheduler.scheduleAtFixedRate(() -> {
long curTime = duringTime.addAndGet(this.mag); // 推荐用 addAndGet
Map<String, TaskAction> actions = actionMap.get(curTime);
if (actions != null && !actions.isEmpty()) {
// 先复制key避免并发删除问题
for (Map.Entry<String, TaskAction> entry : actions.entrySet()) {
actionExecutor.submit(entry.getValue()::doSomeThing);
}
// 全部执行后再清空
actions.clear();
// 或者 actionMap.remove(curTime); 如果你不需要重用这个 key
actionMap.remove(curTime);
}
}, 0, 1, TimeUnit.SECONDS);
}
}
// 取消定时任务
private void cancelTask() {
if (future != null && !future.isCancelled()) {
future.cancel(true);
}
}
public void addAction(long time, TaskAction action) {
actionMap.computeIfAbsent(time, k -> new ConcurrentHashMap<>())
.put(IdUtils.simpleUUID(), action);
}
@Override
public void close() throws Exception {
actionMap.clear();
if (future != null && !future.isCancelled()) {
future.cancel(true);
}
if (scheduler != null && !scheduler.isShutdown()) {
scheduler.shutdown();
}
}
}