![cover](https://img-blog.csdnimg.cn/img_convert/1f20816e15694cf3b56262c1f87e2a14.png)
【重磅干货】基于JDK实现延迟队列,企业实战案例全方位解析!
我们可以使用延迟队列来实现这个流程:当订单生成时,我们将订单信息添加到延迟队列中,并设定一定的延迟时间,比如支付确认后的时间点。我们可以使用延迟队列来实现这个功能:当用户注册时,将发送欢迎消息的请求添加到延迟队列中,并设定一定的延迟时间,比如注册后的24小时。我们可以使用延迟队列来实现这个功能:当任务需要执行时,将任务请求添加到延迟队列中,并设定一定的延迟时间,比如每天的固定时间点。延迟性:我们可
原创 不码不疯魔 不码不疯魔 2023-08-26 12:12 发表于四川
收录于合集
#延迟队列1个
#基于JDK实现延迟队列1个
#取消订单1个
#高频面试题7个
20
23
不疯魔不成活,大家好呀,我是科哥,江湖ID 不码不疯魔
大家好!今天我们将一起探讨一个高级Java技术话题——基于JDK实现延迟队列。这个主题对于许多企业级应用来说都非常重要,因为它可以帮助我们解决一些具有挑战性的业务问题。
在现实生活中,很多场景都需要用到延迟队列。以下就是使用基于JDK的延迟队列的企业级实战场景的三个例子:
1) 订单处理系统:在电商或物流公司中,订单的生成和处理是核心业务之一。当一个订单生成后,我们需要尽快处理该订单,但同时我们也需要等待一些必要的操作完成,比如支付确认、库存更新等。我们可以使用延迟队列来实现这个流程:当订单生成时,我们将订单信息添加到延迟队列中,并设定一定的延迟时间,比如支付确认后的时间点。当延迟期满时,后台处理程序会自动从队列中取出该订单进行后续处理。
2) 消息推送系统:在社交或在线聊天应用中,消息的推送需要及时且准确。但是,某些情况下,我们可能需要延迟一段时间再发送消息,比如在用户注册后的一段时间内发送欢迎消息。我们可以使用延迟队列来实现这个功能:当用户注册时,将发送欢迎消息的请求添加到延迟队列中,并设定一定的延迟时间,比如注册后的24小时。当延迟期满时,后台处理程序会自动从队列中取出该请求,并发送欢迎消息给用户。
3) 定时任务调度:在企业级应用中,我们可能需要定时执行某些任务,比如每天固定时间点进行数据统计、清空临时文件等。我们可以使用延迟队列来实现这个功能:当任务需要执行时,将任务请求添加到延迟队列中,并设定一定的延迟时间,比如每天的固定时间点。当延迟期满时,后台处理程序会自动从队列中取出该请求,并执行相应的任务。
企业实战案例
假设我们正在开发一个电商网站,用户可以在该网站上购买商品。为了提供更好的用户体验,我们希望在用户下单后,能够立即返回订单信息,而不是让用户等待一段时间。但是,我们还需要确保订单能够按时结算,例如在订单生成后的10分钟内进行结算。这时,我们就可以使用基于JDK的延迟队列来解决这个问题。
在用户下单时,我们可以将订单信息放入延迟队列中,并设定10分钟的时间间隔。当时间间隔到达后,后台线程可以从队列中取出该订单信息,并进行结算操作。这样,用户可以立即得到订单信息,同时我们也能保证订单能够按时结算。
为了满足这个需求,我们需要实现一个基于JDK的延迟队列。这个队列应该具有以下特性:
延迟性:我们可以在队列的元素被取出之前,给它们设定一个时间,到了这个时间点,元素才会被取出。
可靠性:队列中的元素不能丢失,必须保证它们能被正确地存入和取出
高并发:在多线程环境下,队列的操作必须保证线程安全。
由于篇幅和格式的限制,我无法在这里提供完整的代码。但我可以为您提供部分代码的示例,以展示如何实现基于JDK的延迟队列。
@Override
public RespResult<String> createOrder(OrderSaveDTO orderSaveDTO) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setId(String.valueOf(DCGenIdUtil.genIdBySnowflake()));
orderInfo.setOrderTime(new Date());
String orderNo = GenerateSequenceUtil.generateSequenceNo();
if (!StringUtils.isEmpty(orderNo)){
orderInfo.setOrderNo(orderNo);
}
orderInfo.setStatus(Constant.ORDER_CREATE);
//拷贝对象(只拷贝不为空的属性)
DCBeanUtil.copyNotNull(orderInfo, orderSaveDTO);
//保存订单
orderMapper.saveOrderInfo(orderInfo);
// 添加延时支付取消订单任务
JDKDelayQueue.addDelayTaskWithSeconds(orderInfo, 2, PayOrderCancelWithJDKListener.class);
return RespResult.success(orderInfo.getOrderNo());
}
/**
* 基于jdk DelayQueue初始化队列监听
*/
@Slf4j
@Component
public class JDKDelayedQueueInit implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
startThread(applicationContext.getBeansOfType(JDKDelayedQueueListener.class));
}
/**
* 启动线程获取队列
* @param map 任务回调监听
*/
private <T> void startThread(Map<String, JDKDelayedQueueListener> map) {
//由于此线程需要常驻,可以新建线程,不用交给线程池管理
Thread thread = new Thread(() -> {
log.info("启动监听JDK延时队列线程!!!");
while (true) {
for (Map.Entry<String, JDKDelayedQueueListener> taskEventListenerEntry : map.entrySet()) {
String queueName = taskEventListenerEntry.getValue().getClass().getSimpleName();
try {
JDKDelayTask<T> jdkDelayTask = JDKDelayQueue.delayQueue.poll();
if(ObjectUtil.isNull(jdkDelayTask)){
try{
// 睡眠一下,防止竞争太激烈, 对CPU产生影响
Thread.sleep(1000);
}catch (Exception e){
log.error(e.getMessage(),e);
}
continue;
}
T t = jdkDelayTask.getBody();
if(t == null){
continue;
}
// 重新设置traceId
TraceHelper.getCurrentTrace();
long start = System.currentTimeMillis();
log.info("开始执行业务逻辑,queueName:{},data:{}",queueName,JSONUtil.toJsonStr(t));
taskEventListenerEntry.getValue().execute(t);
log.info("执行业务逻辑结束, 总耗时:{}ms", System.currentTimeMillis() - start);
} catch (Exception e) {
log.error("启动监听JDK延时队列线程系统异常! errMsg:{}", e.getMessage() ,e);
}
}
}
});
thread.setName("jdk-delayqueue");
thread.setDaemon(true);
thread.start();
}
}
点击下方公众号进入关注,后台回复【JDK延迟队列】即可获取如上图所有源码,大量的商用级方案已经更新,记得关注,免费领取,标记星号哟!!!
更多推荐
所有评论(0)