使用 Delayed和Runnable 实现延时队列
Task
package com.yymt.common.zaxq.entity.threeComment.task;
import com.google.common.primitives.Ints;
import com.yymt.common.validator.Assert;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public abstract class Task implements Delayed, Runnable{
private String id = "";
private long start = 0;
public Task(String id, long delayInMilliseconds){
this.id = id;
this.start = System.currentTimeMillis() + delayInMilliseconds;
}
/**
*
* @param id 任务id
* @param date 开始执行的日期时间
*/
public Task(String id, Date date){
Assert.isEmpty(date,"开始执行的日期时间不能为空");
this.id = id;
this.start = date.getTime();
}
public String getId() {
return id;
}
@Override
public long getDelay(TimeUnit unit) {
long diff = this.start - System.currentTimeMillis();
return unit.convert(diff, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return Ints.saturatedCast(this.start - ((Task) o).start);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!(o instanceof Task)) {
return false;
}
Task t = (Task)o;
return this.id.equals(t.getId());
}
@Override
public int hashCode() {
return this.id.hashCode();
}
}
CommentTaskService 任务管理
package com.yymt.common.zaxq.entity.threeComment.task;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.yymt.common.utils.constant.Values;
import com.yymt.common.zaxq.entity.threeComment.ThreeCommentCommunityEntity;
import com.yymt.common.zaxq.entity.threeComment.constant.ThreeCommentConstant;
import com.yymt.common.zaxq.service.threeComment.ThreeCommentCommunityService;
import org.apache.poi.ss.formula.functions.Today;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executors;
@Component
public class CommentTaskService {
@Autowired
private ThreeCommentCommunityService threeCommentCommunityService;
private DelayQueue<Task> delayQueue = new DelayQueue<Task>();
@PostConstruct
private void init() {
initAddDelayQueue();
Executors.newSingleThreadExecutor().execute(() -> {
while (true) {
try {
Task task = delayQueue.take();
task.run();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 初始化时查询所有不是已结束的任务
*/
private void initAddDelayQueue() {
List<ThreeCommentCommunityEntity> list = threeCommentCommunityService.lambdaQuery()
.in(ThreeCommentCommunityEntity::getTaskStatus,
Arrays.asList(ThreeCommentConstant.TaskStatusEnum.TO_BEGIN.getCode(),
ThreeCommentConstant.TaskStatusEnum.IN_PROGRESS.getCode()))
.groupBy(ThreeCommentCommunityEntity::getTaskId).list();
list.stream().forEach(e -> {
handleTaskStatus(e.getTaskId(), e.getCommentStartTime(), e.getCommentEndTime());
});
}
/**
* 处理任务状态
*
* @param taskId 任务id
* @param commentStartTime 测评开始时间
* @param commentEndTime 测评结束时间
*/
public void handleTaskStatus(Integer taskId, Date commentStartTime, Date commentEndTime) {
DateTime currentDate = DateUtil.date();
if (DateUtil.compare(currentDate, commentEndTime) >= Values.N_0) {
// 已结束
threeCommentCommunityService.updateTaskStatus(taskId, ThreeCommentConstant.TaskStatusEnum.END.getCode());
} else if (DateUtil.compare(currentDate, commentStartTime) >= Values.N_0) {
// 进行中
threeCommentCommunityService.updateTaskStatus(taskId, ThreeCommentConstant.TaskStatusEnum.IN_PROGRESS.getCode());
addTask(new UpdateThreeCommentTaskStatus(taskId, commentEndTime));
} else {
// 未开始
threeCommentCommunityService.updateTaskStatus(taskId, ThreeCommentConstant.TaskStatusEnum.TO_BEGIN.getCode());
addTask(new UpdateThreeCommentTaskStatus(taskId, commentStartTime));
}
}
public void addTask(Task task) {
if (!delayQueue.contains(task)) {
delayQueue.add(task);
}
}
public void removeTask(Task task) {
delayQueue.remove(task);
}
}
UpdateThreeCommentTaskStatus 任务的具体业务
package com.yymt.common.zaxq.entity.threeComment.task;
import com.yymt.common.utils.SpringContextUtils;
import com.yymt.common.zaxq.entity.threeComment.ThreeCommentTaskEntity;
import com.yymt.common.zaxq.service.threeComment.ThreeCommentTaskService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.Date;
public class UpdateThreeCommentTaskStatus extends Task {
private final static String TASK_PRE = "threeCommentTask-";
private final Log logger = LogFactory.getLog(UpdateThreeCommentTaskStatus.class);
private Integer taskId;
public UpdateThreeCommentTaskStatus(Integer taskId, long delayInMilliseconds) {
super(TASK_PRE + taskId, delayInMilliseconds);
this.taskId = taskId;
}
public UpdateThreeCommentTaskStatus(Integer taskId, Date date) {
super(TASK_PRE + taskId, date);
this.taskId = taskId;
}
@Override
public void run() {
logger.info("系统开始处理三评的延时任务" + taskId);
// 如果已经执行到这里则说明延时队列中已经没有这个任务(取出了任务)。这里执行完就结束了,如果需要这个任务下次继续执行,则可以在此继续添加任务。
ThreeCommentTaskService threeCommentTaskService = SpringContextUtils.getBean(ThreeCommentTaskService.class);
ThreeCommentTaskEntity taskEntity = threeCommentTaskService.getById(taskId);
// 处理任务状态
CommentTaskService commentTaskService = SpringContextUtils.getBean(CommentTaskService.class);
commentTaskService.handleTaskStatus(taskId, taskEntity.getCommentStartTime(), taskEntity.getCommentEndTime());
logger.info("系统结束处理三评的延时任务" + this.taskId);
}
}
调用
// 处理任务状态
commentTaskService.handleTaskStatus(taskEntity.getId(), taskEntity.getCommentStartTime(), taskEntity.getCommentEndTime());