一. 知識要點
- delayQueue相關api
- 線程池知識點
- spring異步註解@Async配置和使用
二. 主要代碼
- 訂單類
public class Message implements Delayed {
/** 創建時間 10分鐘以後, 測試可以降低該值 */
private static final int SECOND_NUM = 600;
/**訂單id*/
private int id;
/**訂單狀態*/
private String state;
/**訂單創建時間*/
private Date createTime;
public Message(int id, String state, Date createTime) {
this.id = id;
this.state = state;
this.createTime = createTime;
}
public int getId() {
return id;
}
public String getState() {
return state;
}
public Date getCreateTime() {
return createTime;
}
public void setId(int id) {
this.id = id;
}
public void setState(String state) {
this.state = state;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
/**
*獲取訂單過期時間
*/
private Date getCancelTime(Date createTime) {
return Date.from(createTime.toInstant().plusSeconds(SECOND_NUM));
}
/**
* 判斷元素是否過期(小於等於0時過期)
*
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(getCancelTime(createTime).getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public String toString() {
return "Message{" +
"id=" + id +
", state='" + state + '\'' +
", createTime=" + createTime +
'}';
}
/**
* 根據元素過期時間排序, 哪個元素最早到過期時間, 就排在前面
*
*/
@Override
public int compareTo(Delayed o) {
Message msg = (Message) o;
return Long.compare(this.createTime.getTime(), msg.getCreateTime().getTime());
}
}
- sping配置線程池(數據僅供參考, 根據實際業務配置參數和拒絕策略)
<task:annotation-driven executor="asyncExecutor"/>
<task:executor id="asyncExecutor" pool-size="10-50" queue-capacity="500" keep-alive="200" rejection-policy="CALLER_RUNS"/>
- 業務層主要代碼(異步方法)
@Async
@Override
public void delayClose(Message msg) {
// 初始化delayQueue(如果之前有過期未處理的訂單, 可以放在這裏)
List<Message > unpaidOrder = orderMapper.getOvertimeAndUnpaidOrder();
DelayQueue<Message > queue = new DelayQueue<>();
if (!unpaidOrder.isEmpty()) {
queue.addAll(unpaidOrder);
}
// 將最近的一條訂單添加進去
queue.add(msg);
while (!queue.isEmpty()) {
// 關閉未支付的訂單
cancelOrder(queue);
}
}
private void cancelOrder(DelayQueue<Message > queue) {
try {
Message msg = queue.take();
// 判斷支付狀態
if ("unpaid".equarls(msg.state)) {
// 修改訂單狀態
}
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}