目的
当订单超过指定时间(毫秒),未支付时,系统自动取消订单。
方案
初步方案
1、定时从数据库获取待取消订单, 放入集合中。
2、将剩余10分钟内待取消订单创建线程,加入(缓存)线程池中,休眠(取消时间-当前时间)后执行取消任务。
3、任务执行完成后移除任务。
缺点:未限制线程数量。如果某个时间段退款过多,会导致创建过多线程。
优化方案1
1、将上述方案缓存线程池,修改为定长线程池。
缺点:运行线程占满时,会导致后续新增的取消订单(退款时间小于休眠中的订单),无法按照指定时间执行。
原因:例如线程池中,可同时执行的线程数为2。当前线程池中,已有两个待取消订单在执行队列中(休眠了执行时间后执行)。导致新增的取消订单任务,需等待前两个中的某一个,执行完成后,才能执行新增的取消订单任务。
最终方案 (如有其他方案、此方案有待改进的地方,欢迎评论一起探讨)
1、定时从数据库获取待取消订单, 放入集合中。将集合按照取消时间,从小到大排序。并通知步骤2。
2、获取集合中,第一个任务的订单取消时间,wait(订单取消时间-当前时间)后将线程将线程加入线程池中,执行取消订单任务。无任务时wait()。
3、任务执行完成后移除任务。
简易流程图.png
实现代码 (待删除无用代码)
package com.gtmc.uccs.common.util;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;
/**
* 定时处理工具类
*
* @description: 定时处理工具类
* @author: chenfei
* @create: 2020-12-23 16:21:55
*/
@Slf4j
public abstract class TimingProcess {
/**
* 执行任务的线程池
*/
private final ExecutorService taskExecuteThreadPool;
/**
* 待执行的任务队列
*/
private final List> taskQueue = Collections.synchronizedList(new LinkedList>());
/**
* 执行中的任务队列
*/
private final List> readiedTaskQueue = Collections.synchronizedList(new LinkedList>());
/**
* 调度程序占用的线程数
*/
private final int processTread = 2;
/**
* 循环调用间隔
*/
private int sleepTime;
private static final SimpleDate