参考文章:https://www.cnblogs.com/liboware/p/17155012.html
代码:
@Data
public class TaskQueue implements Serializable {
/**
* 任务唯一标识
*/
private long taskId;
/**
* 延迟时间
*/
private int delayTime = 10;
/**
* 任务执行的时间点
*/
private Date schedulerExecuteAt;
/**
* 任务创建时间
*/
private Date createTime;
/**
* 任务描述
*/
private String desc;
/**
* 重试次数
*/
private int retryCount = 0;
/**
* 已经重试次数
*/
private int retriedCount = 0;
public void setTaskTime() {
Date creatTime = new Date();
this.setCreateTime(creatTime);
Calendar calendar = Calendar.getInstance();
calendar.setTime(creatTime);
calendar.add(Calendar.SECOND, this.getDelayTime());
// 获取延后后的时间
Date newDate = calendar.getTime();
this.setSchedulerExecuteAt(newDate);
}
public boolean doReTryTask() {
if (this.retriedCount < this.retryCount) {
this.retriedCount++;
return true;
}
return false;
}
}
public interface Timer<T extends TaskQueue> {
/**
* 添加任务
*
* @param task 业务逻辑
* @param t 任务信息
* @return this
*/
AbstractTimeWheel<T> newTask(TimerTask<T> task, T t);
/**
* 重试任务
*
* @param t 任务信息
* @return this
*/
AbstractTimeWheel<T> reTryTask(T t);
}
@Data
public abstract class AbstractTimeWheel<T extends TaskQueue> implements Timer<T> {
/**
* 当前所处时间
*/
private LocalDateTime currentTime;
/**
* 最近的任务时间
*/
private LocalDateTime latestTaskTime;
/**
* 任务树
*/
private ListSearchUtil<T> taskTree = new ListSearchUtil<>();
/**
* 任务执行逻辑
*/
private Map<Long, TimerTask<T>> taskMap = new HashMap<>(16);
/**
* 任务运行情况 0停止,1启动
*/
private int wheelStatus = 0;
/**
* TODO 测试执行线程,之改为配置
*/
public static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(1, 1, 3, TimeUnit.MINUTES, new LinkedBlockingQueue<>(10000),
new ThreadFactory() {
private final AtomicLong threadIndex = new AtomicLong(0);
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, MessageFormat.format("{0}_{1}", "timeWheelDo", threadIndex.incrementAndGet()));
thread.setDaemon(true);
return thread;
}
}, new ThreadPoolExecutor.CallerRunsPolicy());
/**
* 定时任务
*/
public static final ScheduledThreadPoolExecutor SCHEDULED = new ScheduledThreadPoolExecutor(2, new ThreadFactory() {
private final AtomicLong threadIndex = new AtomicLong(0);
@Override
public Thread newThread(@Nonnull Runnable runnable) {
Thread thread = new Thread(runnable, MessageFormat.format("{0}_{1}", "timeWheelScheduled", threadIndex.incrementAndGet()));
thread.setDaemon(true);
return thread;
}
});
@Override
public AbstractTimeWheel<T> newTask(TimerTask<T> task, T t) {
startTimeWheel();
t.setTaskTime();
taskTree.add(this::getKeyFromTask, t);
taskMap.put(t.getTaskId(), task);
return this;
}
/**
* 获取key
*
* @param t 任务信息
* @return 时间key
*/
public abstract String getKeyFromTask(T t);
/**
* 获取当前已过期未执行的任务,执行,完成后清理任务
*
* @param now 现在的时间
*/
public abstract void getTaskAndNext(LocalDateTime now);
/**
* 启动时间轮
*/
public abstract void startTimeWheel();
}
@Slf4j
public class TimeWheel<T extends TaskQueue> extends AbstractTimeWheel<T> {
@Override
public String getKeyFromTask(T t) {
return DateUtil.format(t.getSchedulerExecuteAt(), DateUtil.YYYYMMDDHHMMSS);
}
@Override
public void getTaskAndNext(LocalDateTime now) {
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = now.atZone(zoneId);
String format = DateUtil.format(Date.from(zdt.toInstant()), DateUtil.YYYYMMDDHHMMSS);
List<T> taskList = super.getTaskTree().searchWordDfs(format);
if (CollectionUtils.isNotEmpty(taskList)) {
taskList.forEach(task -> {
TimerTask<T> tTimerTask = super.getTaskMap().get(task.getTaskId());
EXECUTOR.submit(() -> {
if (task.getRetriedCount() == 0) {
log.info("正常执行任务:{}", task);
} else {
log.info("任务进行重试,当前第{}次,还剩{}次,任务信息:{}", task.getRetriedCount(), task.getRetryCount() - task.getRetriedCount(), task);
}
boolean run = tTimerTask.run(task);
if (!run && task.doReTryTask()) {
this.reTryTask(task);
} else {
super.getTaskMap().remove(task.getTaskId());
}
});
});
super.getTaskTree().deleteNode(format, (k1, k2) -> Integer.parseInt(k1) >= Integer.parseInt(k2));
}
}
@Override
public void startTimeWheel() {
if (super.getWheelStatus() == 0) {
synchronized (this) {
if (super.getWheelStatus() == 0) {
log.info("启动定时线程==========");
super.setWheelStatus(1);
SCHEDULED.scheduleAtFixedRate(() -> {
LocalDateTime localDateTime = Optional.ofNullable(super.getCurrentTime()).orElse(LocalDateTime.now()).plusSeconds(1);
super.setCurrentTime(localDateTime);
this.getTaskAndNext(localDateTime);
}, 0, 1, TimeUnit.SECONDS);
}
}
}
}
@Override
public AbstractTimeWheel<T> reTryTask(T t) {
t.setTaskTime();
super.getTaskTree().add(this::getKeyFromTask, t);
return this;
}
}
public interface TimerTask<T extends TaskQueue> {
/**
* 任务执行逻辑
*
* @param t 任务信息
* @return
*/
boolean run(T t);
}
调用示例:
public static final TimeWheel<TaskQueue> TASK_QUEUE_TIME_WHEEL=new TimeWheel<>();
@Override
public TestVo test(MyClass fo) {
TaskQueue taskQueue = new TaskQueue();
taskQueue.setTaskId(RandomCodeUtil.generateLong(19));
taskQueue.setDelayTime(5);
taskQueue.setRetryCount(5);
TimerTask<TaskQueue> timerTask = queue -> {
log.info("测试逻辑执行");
return false;
};
TASK_QUEUE_TIME_WHEEL.newTask(timerTask, taskQueue);
log.info("fo:{}", fo);
return new TestVo("测试一下");
}