队列送券的实际应用--ConcurrentLinkedQueue并发队列
1、TicketQueue.java--队列封装类,负责如下职责:
a、把活动登记对象放入队列中
b、从队列中获取活动登记对象,并派券
package com.datong.pear.ticket; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; import com.datong.pear.system.common.Constants; import com.datong.pear.system.common.Result; /** * 活动登记队列 * * @author jqlin */ public class TicketQueue { private static ConcurrentLinkedQueue<ActivityRecordModel> linkedQueue = new ConcurrentLinkedQueue<ActivityRecordModel>(); private static final Logger logger = Logger.getLogger(TicketQueue.class); public static boolean isRunning = false; /** * 活动登记对象放入队列中 * * @param activityRecord * @author jqlin */ public static void offer(ActivityRecordModel activityRecord) { if(activityRecord == null){ logger.info(String.format("%s activityRecord is null", TicketQueue.class.getName())); return; } if(NumberUtils.toLong(activityRecord.getId(), 0) == 0L){ logger.info(String.format("%s activityRecord.id is illegal,activityRecord.id=%s", TicketQueue.class.getName(), activityRecord.getId())); return; } logger.info(String.format("%s 即将放入队列的活动登记信息:%s", TicketQueue.class.getName(), activityRecord)); if(activityRecord.getState() != Constants.ActivityRecordStatus.WPF){ logger.info(String.format("%s activityRecordId=%s 状态不是未派发,无法放入队列", TicketQueue.class.getName(), activityRecord.getId())); return; } logger.info(String.format("%s activityRecordId=%s 准备放入队列", TicketQueue.class.getName(), activityRecord.getId())); linkedQueue.offer(activityRecord); logger.info(String.format("----setActivityRecordId=%s *****", activityRecord.getId())); logger.info(String.format("%s activityRecordId=%s 放入队列成功", TicketQueue.class.getName(), activityRecord.getId())); logger.info("**********************************************************************"); } /** * 从队列中获取活动登记对象,并派券 * * @return * @author jqlin */ public static synchronized void pollAndSendTicket(TicketService ticketService) { isRunning = true; logger.info("准备从队列中获取活动登记对象,并派券..."); if(linkedQueue != null && !linkedQueue.isEmpty()){ ActivityRecordModel activityRecordModel = null; while (true) { Iterator<ActivityRecordModel> arIterator = linkedQueue.iterator(); if(!arIterator.hasNext()){ try { Thread.sleep(1000); } catch (InterruptedException e) { logger.info("队列派券异常中断"); } continue; } activityRecordModel = arIterator.next(); logger.info(String.format("----getActivityRecordId=%s, Thread=%s *****", activityRecordModel.getId(), Thread.currentThread().getId())); logger.info(String.format("%s 从队列中获取的活动登记信息:%s", TicketQueue.class.getName(), activityRecordModel)); logger.info(String.format("%s activityRecordId=%s 准备移出队列", TicketQueue.class.getName(), activityRecordModel.getId())); linkedQueue.remove(activityRecordModel); logger.info(String.format("%s activityRecordId=%s 移出队列成功", TicketQueue.class.getName(), activityRecordModel.getId())); logger.info(String.format("%s activityRecordId=%s 队列派券开始", TicketQueue.class.getName(), activityRecordModel.getId())); Result result = ticketService.sendTicket(activityRecordModel); logger.info(String.format("%s 活动登记派券接口返回信息:", TicketQueue.class.getName())); logger.info(result); logger.info(String.format("%s 活动登记派券结束", TicketQueue.class.getName())); logger.info("**********************************************************************"); } } else { logger.info("队列中活动登记对象为空,没有数据可派券..."); } isRunning = false; } }
2、启动线程执行队列
/** * 通过队列派券 * * @param ar * @param ticketService * @author jqlin */ private synchronized void sendTicketByQueue(ActivityRecordModel ar, final TicketService ticketService) { final ActivityRecordModel activityRecord = ar; TicketQueue.offer(activityRecord); //队列为空,启动一个线程 if(!TicketQueue.isRunning) { new Thread(new Runnable(){ @Override public void run() { logger.info("启动一个线程,放入队列派券..."); TicketQueue.pollAndSendTicket(ticketService); } }).start(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」