/*** * 创建订单 * @param seckillid * @param userid */ @Override public void saveOrder(Long seckillid, String userid) { //获取队列中的商品,如果能够获取,则商品存在,可以下单 //这样可以避免多个用户同时抢购意见商品重复下单 Long goodsId = (Long) redisTemplate.boundListOps(SysContant.SECKILL_PREFIX + seckillid).rightPop(); if(goodsId==null){ throw new RuntimeException("已售罄!"); } //获取商品详情 SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(SeckillGoods.class.getSimpleName()).get(seckillid); //略.... } |
@Component //@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //采用原型模式 public class CreateOrder implements Runnable { @Autowired private SeckillGoodsMapper seckillGoodsMapper; @Autowired private RedisTemplate redisTemplate; @Autowired private IdWorker idWorker; @Override public void run() { //从Redis中获取排队信息,然后依次下单 OrderRecode orderRecode = (OrderRecode) redisTemplate.boundListOps(OrderRecode.class.getSimpleName()).rightPop(); if(orderRecode!=null){ //获取队列中的商品,如果能够获取,则商品存在,可以下单 //这样可以避免多个用户同时抢购意见商品重复下单 Long goodsId = (Long) redisTemplate.boundListOps(SysContant.SECKILL_PREFIX + orderRecode.getGoodsId()).rightPop(); if(goodsId==null){ //售罄 //将用户从排队中移除,否则用户不能继续排队 redisTemplate.boundSetOps(SysContant.SECKILL_USER).remove(orderRecode.getUserid()); return; } //获取商品详情 SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(SeckillGoods.class.getSimpleName()).get(orderRecode.getGoodsId()); if(seckillGoods!=null){ //创建订单 SeckillOrder order = new SeckillOrder(); order.setId(idWorker.nextId()); order.setSeckillId(orderRecode.getGoodsId()); order.setMoney(seckillGoods.getCostPrice()); //秒杀价格 order.setUserId(orderRecode.getUserid()); order.setSellerId(seckillGoods.getSellerId()); order.setCreateTime(new Date()); order.setStatus("0"); //0未支付,1已支付 //订单数据存入Reids redisTemplate.boundHashOps(SeckillOrder.class.getSimpleName()).put(orderRecode.getUserid(),order); //Reids数据递减 ---- 当库存为1的时候。有并发 加个同步锁。 seckillGoods.setStockCount(seckillGoods.getStockCount()-1); if(seckillGoods.getStockCount()<=0){ //商品卖完,同步数据库 seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods); //清除缓存 redisTemplate.boundHashOps(SeckillGoods.class.getSimpleName()).delete(seckillGoods.getId()); }else{ //Redis库存递减同步 redisTemplate.boundHashOps(SeckillGoods.class.getSimpleName()).put(seckillGoods.getId(),seckillGoods); } //抢购人数削减 redisTemplate.boundValueOps(SysContant.SECKILL_COUNT_GOODSID_PREFIX+orderRecode.getGoodsId()).increment(-1); } } } } |
<!-- 线程池配置 --> <bean class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" id="executor"> <!-- 核心线程数,默认为1--> <property name="corePoolSize" value="10" /> <!--最大线程数,默认为Integer.MAX_VALUE--> <property name="maxPoolSize" value="50" /> <!--队列最大长度,一般需要设置值>=notifyScheduledMainExecutor.maxNum;默认为Integer.MAX_VALUE--> <property name="queueCapacity" value="10000" /> <!--线程池维护线程所允许的空闲时间,默认为60s--> <property name="keepAliveSeconds" value="300" /> <!--线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者--> <property name="rejectedExecutionHandler"> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property> </bean> |
@Autowired private RedisTemplate redisTemplate; @Autowired private CreateOrder createOrder; @Autowired private ThreadPoolTaskExecutor executor; /*** * 创建订单 * @param seckillid * @param userid */ @Override public void saveOrder(Long seckillid, String userid) { //获取队列中的商品,如果能够获取,则商品存在,可以下单 //这样可以避免多个用户同时抢购意见商品重复下单 //获取商品详情 SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(SeckillGoods.class.getSimpleName()).get(seckillid); if(seckillGoods==null || seckillGoods.getStockCount()<=0){ throw new RuntimeException("已售罄!"); } //判断用户是否正在排队 Boolean member = redisTemplate.boundSetOps(SysContant.SECKILL_USER).isMember(userid); if(member){ //判断用户是否下单 Object order = redisTemplate.boundHashOps(SeckillOrder.class.getSimpleName()).get(userid); if(order!=null){ throw new RuntimeException("您有未支付的订单!"); } throw new RuntimeException("正在排队中!"); } //当前商品秒杀的人数 Long seckillusercount = redisTemplate.boundValueOps(SysContant.SECKILL_COUNT_GOODSID_PREFIX + seckillid).increment(0); //当前商品的剩余个数 if((seckillGoods.getStockCount().intValue()+200)<=seckillusercount){ //超过限制,这里的200可以自定义 throw new RuntimeException("当前商品抢购人数过多"); } //下单数据加入缓存 OrderRecode orderRecode = new OrderRecode(seckillid, userid); redisTemplate.boundListOps(OrderRecode.class.getSimpleName()).leftPush(orderRecode); //排队记录加入缓存 redisTemplate.boundSetOps(SysContant.SECKILL_USER).add(userid); //抢购人数记录 redisTemplate.boundValueOps(SysContant.SECKILL_COUNT_GOODSID_PREFIX+seckillid).increment(1); //调用线程执行 executor.execute(createOrder); } |
1.png (36.73 KB, 下载次数: 11)
2.png (40.08 KB, 下载次数: 12)
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |