SnatchMaskServiceImpl.java 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package com.sw.service.impl;
  2. import com.sw.activemq.producer.IMessageProducerService;
  3. import com.sw.domain.TMask;
  4. import com.sw.service.SnatchMaskService;
  5. import com.sw.service.TMaskService;
  6. import com.sw.service.TOrderService;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.redisson.api.RLock;
  9. import org.redisson.api.RedissonClient;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.beans.factory.annotation.Value;
  12. import org.springframework.data.redis.connection.RedisConnection;
  13. import org.springframework.data.redis.core.RedisTemplate;
  14. import org.springframework.stereotype.Service;
  15. import org.springframework.transaction.annotation.Transactional;
  16. import javax.annotation.Resource;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. import java.util.concurrent.TimeUnit;
  20. import java.util.concurrent.locks.Condition;
  21. import java.util.concurrent.locks.ReentrantLock;
  22. /**
  23. * @Description TODO
  24. * @Author DingLan
  25. * @Date 2022/2/18 13:22
  26. **/
  27. @Service
  28. @Slf4j
  29. public class SnatchMaskServiceImpl implements SnatchMaskService {
  30. @Autowired
  31. private TMaskService maskService;
  32. @Autowired
  33. private TOrderService orderService;
  34. @Resource
  35. private RedisTemplate redisTemplate;
  36. @Resource
  37. private IMessageProducerService mqService;
  38. @Autowired
  39. private RedissonClient redissonClient;
  40. @Value("${amount}")
  41. private Integer amount;
  42. Object o = new Object();
  43. ReentrantLock reentrantLock = new ReentrantLock();
  44. Condition condition = reentrantLock.newCondition();
  45. @Override
  46. @Transactional
  47. public String doSnatch(Integer uid, Integer maskId) {
  48. //1.get the amount of remaining masks
  49. TMask mask = maskService.getById(maskId);
  50. if (mask.getMaskStock() >= amount) {
  51. //3.create order
  52. int res = orderService.creatOrder(uid, maskId);
  53. //4.decrease the stock of mask
  54. Boolean flag = maskService.decrease(maskId, mask.getMaskStock() - amount);
  55. if (res > 0 && flag) {
  56. //3. add to successUserUids
  57. redisTemplate.opsForSet().add("successUserUids", uid);
  58. return "恭喜你 抢购成功";
  59. } else {
  60. return "抢购失败 稍后重试";
  61. }
  62. }
  63. return "库存不足 抢购失败";
  64. }
  65. /**
  66. * 查看redis库存是否充足
  67. */
  68. @Override
  69. public Boolean checkAndDecrRemaining(Integer mid) {
  70. RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
  71. Boolean flag = false;
  72. final byte[] key = redisTemplate.getKeySerializer().serialize("mask-setnx-mq-" + mid);
  73. final byte[] value = redisTemplate.getValueSerializer().serialize(1);
  74. try {
  75. //
  76. // while (!connection.setNX(redisTemplate.getKeySerializer().serialize("mask-setnx-mq-" + mid), redisTemplate.getValueSerializer().serialize(1))) {
  77. // Thread.sleep(3);
  78. // }
  79. if(redisTemplate.opsForValue().setIfAbsent("mask-setnx-mq-" + mid, Thread.currentThread().getName(), 1000, TimeUnit.MILLISECONDS)) {
  80. Integer remaining = Integer.valueOf(redisTemplate.opsForHash().get("usableMasks", "mask-" + mid).toString());
  81. System.out.println("库存扣减前:" + remaining + "---" + Thread.currentThread());
  82. if (remaining.compareTo(amount) >= 0) {
  83. Long res = redisTemplate.opsForHash().increment("usableMasks", "mask-" + mid, -amount);
  84. System.out.println("库存扣减后:" + "increment res : " + res + "---" + Thread.currentThread());//扣减之后的库存数量
  85. flag = true;
  86. } else {
  87. flag = false;
  88. }
  89. connection.del(key);
  90. connection.close();
  91. return flag;
  92. }else {
  93. return flag;
  94. }
  95. } finally {
  96. connection.close();
  97. }
  98. // reentrantLock.lock();
  99. // try {
  100. // Integer remaining = Integer.valueOf(redisTemplate.opsForHash().get("usableMasks", "mask-" + mid).toString());
  101. // System.out.println("库存扣减前:" + remaining + "---" + Thread.currentThread());
  102. // if (remaining.compareTo(amount) >= 0) {
  103. // Long res = redisTemplate.opsForHash().increment("usableMasks", "mask-" + mid, -amount);
  104. // System.out.println("库存扣减后:" + "increment res : " + res + "---" + Thread.currentThread());//扣减之后的库存数量
  105. // return true;
  106. // } else {
  107. // return false;
  108. // }
  109. // } finally {
  110. // reentrantLock.unlock();
  111. // }
  112. /* synchronized (o) {
  113. // Integer remaining = 0;
  114. Integer remaining = Integer.valueOf(redisTemplate.opsForHash().get("usableMasks", "mask-" + mid).toString());
  115. System.out.println("库存扣减前:"+remaining+"---" + Thread.currentThread());
  116. if(remaining.compareTo(amount) >= 0) {
  117. Long res = redisTemplate.opsForHash().increment("usableMasks", "mask-" + mid, -amount);
  118. System.out.println("库存扣减后:"+"increment res : "+res +"---" + Thread.currentThread());//扣减之后的库存数量
  119. return true;
  120. }else{
  121. return false;
  122. }
  123. }*/
  124. }
  125. @Override
  126. public String doSnatchMQ(Integer uid, Integer mid) {
  127. Map<String, Object> agrs = new HashMap<>();
  128. agrs.put("uid", uid);
  129. agrs.put("mid", mid);
  130. mqService.sendMessage(agrs);
  131. return "抢购成功 请稍后查看订单";
  132. }
  133. /**
  134. * mq消费端 调用方法 扣减sql库存 创建未支付订单
  135. *
  136. * @param uid
  137. * @param maskId
  138. */
  139. @Override
  140. // @Transactional
  141. public void doDecrAndCreateOrder(Integer uid, Integer maskId) {
  142. RLock lock = redissonClient.getLock("mask-" + maskId);
  143. String threadName = Thread.currentThread().getName();
  144. try {
  145. if (lock.tryLock(1000, TimeUnit.MILLISECONDS)) {
  146. log.info("线程:{} 获取锁", threadName);
  147. Thread.sleep(3000);
  148. log.info("doSnatch方法执行结果:{}", this.doSnatch(uid, maskId));
  149. lock.unlock();
  150. log.info("{}:业务执行完成", threadName);
  151. // break;
  152. }
  153. } catch(InterruptedException e){
  154. e.printStackTrace();
  155. }
  156. }
  157. }