准备工作,查询商品信息,将剩余数量同步到redis中
Jedis jedis = jedisPool.getResource();
BuyGood good=buyGoodService.getById(good_id);
jedis.set("residue"+good_id, good.getResidue()+"");
jedisPool.returnResource(jedis);
请求封装对象
public class BuyRequest {
private int good_id;//商品id
private int user_id;//用户ID
private int order_id;//订单id
private BuyOrders buyOrders;//订单信息
private int response_status;//0:未处理;1:正常;2:异常
public BuyOrders getBuyOrders() {
return buyOrders;
}
public void setBuyOrders(BuyOrders buyOrders) {
this.buyOrders = buyOrders;
}
public int getGood_id() {
return good_id;
}
public void setGood_id(int good_id) {
this.good_id = good_id;
}
public int getOrder_id() {
return order_id;
}
public void setOrder_id(int order_id) {
this.order_id = order_id;
}
public int getResponse_status() {
return response_status;
}
public void setResponse_status(int response_status) {
this.response_status = response_status;
}
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
}
处理请求的controller
@Controller
@RequestMapping("/buy")
public class BuyController {
private static BuyQueue<BuyRequest> buyqueue =null;//线程安全的请求队列
@RequestMapping("/addOrders.do")
@ResponseBody
public Object addOrders(BuyRequest buyrequest){
Map<String, Object> results = new HashMap<>();
Jedis jedis = jedisPool.getResource();
try {
//下订单之前,先获取商品的剩余数量
int residue = Integer.valueOf(jedis.get("residue"+buyrequest.getGood_id()));
if(residue<1){//如果剩余数量不足,直接响应客户端“卖完了”
results.put("msg", "卖完了");
results.put("done", false);
BaseLog.info("addOrders results="+JSON.toJSONString(results));
return results;
}
//如果还有剩余商品,就准备将请求放到请求队列中
if(buyqueue==null){//第一次初始化请求队列,队列的容量为当前的商品剩余数量
buyqueue=new BuyQueue<BuyRequest>(residue);
}
if(buyqueue.remainingCapacity()>0){//当队列的可用容量大于0时,将请求放到请求队列中
buyqueue.put(buyrequest);
}else{//当请求队列已满,本次请求不能处理,直接响应客户端提示请求队列已满
results.put("msg", "抢购队列已满,请稍候重试!");
results.put("done", false);
return results;
}
if(!DealQueueThread.excute){//如果线程类的当前执行标志为未执行,即空闲状态,通过线程池启动线程
DealQueueThread dealQueue = new DealQueueThread(buyqueue);
ThreadPoolUtil.pool.execute(dealQueue);
BaseLog.info("Thread.activeCount()="+Thread.activeCount());
}
//请求放入到队列中,即完成下单请求
results.put("done", true);
results.put("msg", "下订单成功");
} catch (Exception e) {
results.put("done", false);
results.put("msg", "下单失败");
BaseLog.info("addOrders results="+JSON.toJSONString(results));
BaseLog.error("addOrders",e);
}finally{
jedisPool.returnResource(jedis);
}
return results;
}
}
处理请求的线程类
@Component
public class DealQueueThread implements Runnable {
private static DealQueueThread dealQueueThread;
@Autowired
BuyGoodService buyGoodService;
@Autowired
BuyOrdersService buyOrdersService;
@Autowired
JedisPool jedisPool;
private Jedis jedis;
private BuyQueue<BuyRequest> buyqueue;
public static boolean excute = false;//线程的默认执行标志为未执行,即空闲状态
public DealQueueThread() {
}
public DealQueueThread(BuyQueue<BuyRequest> buyqueue) {
this.buyqueue = buyqueue;
jedis = dealQueueThread.jedisPool.getResource();
}
@PostConstruct
public void init() {
dealQueueThread = this;
dealQueueThread.buyGoodService = this.buyGoodService;
dealQueueThread.buyOrdersService = this.buyOrdersService;
dealQueueThread.jedisPool = this.jedisPool;
}
@Override
public void run() {
try {
excute = true;//修改线程的默认执行标志为执行状态
//开始处理请求队列中的请求,按照队列的FIFO的规则,先处理先放入到队列中的请求
while (buyqueue != null && buyqueue.size() > 0) {
BuyRequest buyreq = buyqueue.take();//取出队列中的请求
dealWithQueue(buyreq);//处理请求
}
} catch (InterruptedException e) {
BaseLog.error("DealQueueThread:", e);
} finally {
excute = false;
}
}
public synchronized void dealWithQueue(BuyRequest buyreq) {
try {
//为了尽量确保数据的一致性,处理之前先从redis中获取当前抢购商品的剩余数量
int residue = Integer.valueOf(jedis.get("residue" + buyreq.getGood_id()));
if (residue < 1) {//如果没有剩余商品,就直接返回
buyreq.setResponse_status(3);
return;
}
//如果有剩余商品,先在redis中将剩余数量减一,再开始下订单
jedis.decr("residue" + buyreq.getGood_id());
//将数据库中将剩余数量减一,这一步处理可以在队列处理完成之后一次性更新剩余数量
dealQueueThread.buyGoodService.minusResidue(buyreq.getGood_id());
//处理请求,下订单
BuyOrders bo = new BuyOrders();
bo.setGood_id(buyreq.getGood_id());
bo.setUser_id(buyreq.getUser_id());
int order_id = dealQueueThread.buyOrdersService.insert(bo);
BuyOrders orders = dealQueueThread.buyOrdersService.getById(order_id);
buyreq.setOrder_id(order_id);//订单id
buyreq.setBuyOrders(orders);//订单信息
buyreq.setResponse_status(1);//处理完成状态
} catch (Exception e) {
buyreq.setResponse_status(2);//异常状态
BaseLog.error("DealQueueThread dealWithQueue:", e);
}
}
}
BuyQueue:
public class BuyQueue extends ArrayBlockingQueue<BuyRequest> {
public BuyQueue(int capacity) {
super(capacity);
}
}