140 lines
3.4 KiB
Java
140 lines
3.4 KiB
Java
|
|
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();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|