From dbe0c9a61bbec86b0361837894d8582fbd9aa995 Mon Sep 17 00:00:00 2001 From: seesaw Date: Tue, 22 Oct 2024 14:35:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/amount/AmountServiceImpl.java | 6 +- .../amount/CashRechargeServiceImpl.java | 4 +- .../service/amount/DeductionService.java | 5 + .../service/amount/DeductionServiceImpl.java | 94 +++++++++++++++---- .../member/service/amount/LockManager.java | 40 ++++++++ .../service/amount/WxRechargeServiceImpl.java | 3 +- .../service/business/BusinessServiceImpl.java | 3 +- .../storeorder/StoreOrderServiceImpl.java | 46 ++------- 8 files changed, 136 insertions(+), 65 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/LockManager.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/AmountServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/AmountServiceImpl.java index c72398c6..c1accb84 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/AmountServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/AmountServiceImpl.java @@ -22,9 +22,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -52,6 +50,8 @@ public class AmountServiceImpl implements AmountService { @Resource private RechargeLogMapper rechargeLogMapper; + public final static Map userLocks = new WeakHashMap<>(); + @Override public void operateAmount(Long userId, BigDecimal money, BigDecimal cashAmount, BigDecimal giftAmount, BigDecimal wxAmount) { synchronized (userId) { diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/CashRechargeServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/CashRechargeServiceImpl.java index 98ef0d7e..88ea857f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/CashRechargeServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/CashRechargeServiceImpl.java @@ -23,6 +23,8 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import static cn.iocoder.yudao.module.member.service.amount.LockManager.getUserLock; + /** * 现金充值 Service 实现类 * @@ -62,7 +64,7 @@ public class CashRechargeServiceImpl implements CashRechargeService{ BigDecimal giftNewMoney; BigDecimal cashNewAmount; - synchronized (userId){ + synchronized (getUserLock(userId)){ MemberUserDO memberUserDO = userMapper.selectById(userId); //金额变动 memberUserDO.setMoney(memberUserDO.getMoney().add(money)); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionService.java index 7fce51ca..27445cc9 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionService.java @@ -31,4 +31,9 @@ public interface DeductionService { * 减免 */ void reduction(Long userId, BigDecimal money, BigDecimal giftAmount, BigDecimal cashAmount, BigDecimal wxAmount); + + /** + * 超市扣款 + */ + BigDecimal storeDeduction(BigDecimal total, Long userId); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionServiceImpl.java index fa2426ce..ff3f904c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/DeductionServiceImpl.java @@ -18,17 +18,20 @@ import cn.iocoder.yudao.module.member.service.order.OrderService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; import cn.iocoder.yudao.module.member.util.MemberConstants; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.sun.istack.NotNull; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; + import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.CASH_AMOUNT_NOT_ENOUGH; +import static cn.iocoder.yudao.module.member.service.amount.LockManager.getUserLock; /** @@ -58,9 +61,9 @@ public class DeductionServiceImpl implements DeductionService { BigDecimal changeMoney; BigDecimal wxNewMoney; BigDecimal giftNewMoney; - BigDecimal cashNewAmount; + BigDecimal cashNewMoney; - synchronized (userId) { + synchronized (getUserLock(userId)) { MemberUserDO user = userService.getUser(userId); //新的总价 @@ -142,7 +145,7 @@ public class DeductionServiceImpl implements DeductionService { newMoney = user.getMoney(); wxNewMoney = user.getWxAmount(); giftNewMoney = user.getGiftAmount(); - cashNewAmount = user.getCashAmount(); + cashNewMoney = user.getCashAmount(); changeMoney = total; } @@ -154,7 +157,7 @@ public class DeductionServiceImpl implements DeductionService { cardDO.setChangeMoney(changeMoney); cardDO.setFlag(CardDO.MINUS); cardDO.setMoney(newMoney); - cardDO.setCashAmount(cashNewAmount); + cardDO.setCashAmount(cashNewMoney); cardDO.setWxAmount(wxNewMoney); cardDO.setGiftAmount(giftNewMoney); @@ -184,9 +187,9 @@ public class DeductionServiceImpl implements DeductionService { BigDecimal newMoney; BigDecimal wxNewMoney; BigDecimal giftNewMoney; - BigDecimal cashNewAmount; + BigDecimal cashNewMoney; - synchronized (userId) { + synchronized (getUserLock(userId)) { MemberUserDO user = userService.getUser(userId); if (ObjectUtil.isEmpty(user) || user.getCashAmount().compareTo(BigDecimal.ZERO) < 1 || money.compareTo(user.getCashAmount()) > 0) { @@ -198,7 +201,7 @@ public class DeductionServiceImpl implements DeductionService { newMoney = user.getMoney(); wxNewMoney = user.getWxAmount(); giftNewMoney = user.getGiftAmount(); - cashNewAmount = user.getCashAmount(); + cashNewMoney = user.getCashAmount(); } CardDO cardDO = new CardDO(); @@ -209,7 +212,7 @@ public class DeductionServiceImpl implements DeductionService { cardDO.setWxAmount(wxNewMoney); cardDO.setGiftAmount(giftNewMoney); cardDO.setMoney(newMoney); - cardDO.setCashAmount(cashNewAmount); + cardDO.setCashAmount(cashNewMoney); cardService.insertOne(cardDO); } @@ -219,10 +222,10 @@ public class DeductionServiceImpl implements DeductionService { BigDecimal newMoney; BigDecimal wxNewMoney; BigDecimal giftNewMoney; - BigDecimal cashNewAmount; + BigDecimal cashNewMoney; BigDecimal changeMoney = new BigDecimal(amount).divide(new BigDecimal("100")); - synchronized (userId) { + synchronized (getUserLock(userId)) { MemberUserDO user = userService.getUser(userId); user.setWxAmount(user.getWxAmount().subtract(changeMoney)); user.setMoney(user.getMoney().subtract(changeMoney)); @@ -230,7 +233,7 @@ public class DeductionServiceImpl implements DeductionService { newMoney = user.getMoney(); wxNewMoney = user.getWxAmount(); giftNewMoney = user.getGiftAmount(); - cashNewAmount = user.getCashAmount(); + cashNewMoney = user.getCashAmount(); } @@ -244,7 +247,7 @@ public class DeductionServiceImpl implements DeductionService { cardDO.setWxAmount(wxNewMoney); cardDO.setGiftAmount(giftNewMoney); cardDO.setMoney(newMoney); - cardDO.setCashAmount(cashNewAmount); + cardDO.setCashAmount(cashNewMoney); cardService.insertOne(cardDO); } @@ -254,9 +257,9 @@ public class DeductionServiceImpl implements DeductionService { BigDecimal newMoney2; BigDecimal wxNewMoney; BigDecimal giftNewMoney; - BigDecimal cashNewAmount; + BigDecimal cashNewMoney; - synchronized (userId) { + synchronized (getUserLock(userId)) { MemberUserDO user = userService.getUser(userId); BigDecimal oldMoney = user.getMoney(); @@ -305,7 +308,7 @@ public class DeductionServiceImpl implements DeductionService { newMoney2 = user.getMoney(); wxNewMoney = user.getWxAmount(); giftNewMoney = user.getGiftAmount(); - cashNewAmount = user.getCashAmount(); + cashNewMoney = user.getCashAmount(); } @@ -317,7 +320,7 @@ public class DeductionServiceImpl implements DeductionService { cardDO.setWxAmount(wxNewMoney); cardDO.setGiftAmount(giftNewMoney); cardDO.setMoney(newMoney2); - cardDO.setCashAmount(cashNewAmount); + cardDO.setCashAmount(cashNewMoney); cardService.insertOne(cardDO); } @@ -325,12 +328,12 @@ public class DeductionServiceImpl implements DeductionService { @Override public void reduction(Long userId, BigDecimal money, BigDecimal giftAmount, BigDecimal cashAmount, BigDecimal wxAmount) { - BigDecimal NewMoney; + BigDecimal newMoney; BigDecimal giftNewAmount; BigDecimal cashNewAmount; BigDecimal wxNewAmount; - synchronized (userId) { + synchronized (getUserLock(userId)) { MemberUserDO user = userService.getUser(userId); user.setMoney(user.getMoney().add(money)); user.setCashAmount(user.getCashAmount().add(cashAmount)); @@ -338,7 +341,7 @@ public class DeductionServiceImpl implements DeductionService { user.setWxAmount(user.getWxAmount().add(wxAmount)); userService.updateById(user); - NewMoney = user.getMoney(); + newMoney = user.getMoney(); wxNewAmount = user.getWxAmount(); giftNewAmount = user.getGiftAmount(); cashNewAmount = user.getCashAmount(); @@ -348,11 +351,62 @@ public class DeductionServiceImpl implements DeductionService { cardDO.setFlag(CardDO.ADD); cardDO.setChangeMoney(money); cardDO.setType(CostTypeEnum.REFUND.getCode()); - cardDO.setMoney(NewMoney); + cardDO.setMoney(newMoney); cardDO.setWxAmount(wxNewAmount); cardDO.setCashAmount(cashNewAmount); cardDO.setGiftAmount(giftNewAmount); cardService.insertOne(cardDO); } + + @Override + public BigDecimal storeDeduction(BigDecimal total, @NotNull Long userId) { + + BigDecimal newMoney; + BigDecimal wxNewMoney; + BigDecimal giftNewMoney; + BigDecimal cashNewMoney; + synchronized (getUserLock(userId)) { + MemberUserDO user = userService.getUser(userId); + BigDecimal money = user.getMoney(); + if (total.compareTo(money) > 0){ + return money.subtract(total); + } + BigDecimal wxAmount = user.getWxAmount(); + BigDecimal giftAmount = user.getGiftAmount(); + BigDecimal cashAmount = user.getCashAmount(); + user.setMoney(money.subtract(total)); + + //计算金额 + if (total.compareTo(cashAmount) <= 0) { + user.setCashAmount(cashAmount.subtract(total)); + } else { + user.setCashAmount(BigDecimal.ZERO); + BigDecimal total1 = total.subtract(cashAmount); + if (total1.compareTo(giftAmount) <= 0) { + user.setGiftAmount(giftAmount.subtract(total1)); + } else { + user.setGiftAmount(BigDecimal.ZERO); + BigDecimal total2 = total1.subtract(giftAmount); + user.setWxAmount(wxAmount.subtract(total2)); + } + } + userService.updateById(user); + newMoney = user.getMoney(); + wxNewMoney = user.getWxAmount(); + giftNewMoney = user.getGiftAmount(); + cashNewMoney = user.getCashAmount(); + } + + CardDO cardDO = new CardDO(); + cardDO.setUserId(userId); + cardDO.setChangeMoney(total); + cardDO.setFlag(CardDO.MINUS); + cardService.insertOne(cardDO); + cardDO.setMoney(newMoney); + cardDO.setWxAmount(wxNewMoney); + cardDO.setCashAmount(cashNewMoney); + cardDO.setGiftAmount(giftNewMoney); + return cardDO.getMoney(); + } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/LockManager.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/LockManager.java new file mode 100644 index 00000000..93a20a70 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/LockManager.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.member.service.amount; + +import java.lang.ref.WeakReference; +import java.util.concurrent.ConcurrentHashMap; + +public class LockManager { + + private static final ConcurrentHashMap> userLocks = new ConcurrentHashMap<>(); + + private static final ConcurrentHashMap storeLocks = new ConcurrentHashMap<>(); + + + public static Object getUserLock(Long userId) { + // 从 Map 中获取 WeakReference 对象 + WeakReference lockRef = userLocks.get(userId); + Object lock = (lockRef != null) ? lockRef.get() : null; + + if (lock == null) { + // 如果锁对象不存在或者已被回收,创建新的锁对象 + lock = new Object(); + WeakReference newLockRef = new WeakReference<>(lock); + // 使用 putIfAbsent 确保线程安全 + WeakReference existingLockRef = userLocks.putIfAbsent(userId, newLockRef); + if (existingLockRef != null) { + lock = existingLockRef.get(); + if (lock == null) { + // 如果弱引用对象已经被 GC 回收,更新锁对象 + userLocks.put(userId, newLockRef); + } + } + } + return lock; + } + + public static Object getStoreLock(Long storeId) { + // 对每个 userId 生成独立的锁对象,并发地存储在 ConcurrentHashMap 中 + return storeLocks.computeIfAbsent(storeId, k -> new Object()); + } +} + diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/WxRechargeServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/WxRechargeServiceImpl.java index 9176b20f..05f441b4 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/WxRechargeServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/amount/WxRechargeServiceImpl.java @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import static cn.iocoder.yudao.module.member.service.amount.LockManager.getUserLock; /** @@ -56,7 +57,7 @@ public class WxRechargeServiceImpl implements WxRechargeService { BigDecimal cashNewAmount; - synchronized (userId) { + synchronized (getUserLock(userId)) { //获取最新余额 MemberUserDO memberUserDO = userMapper.selectById(userId); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java index d17a3870..b5b5a701 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/business/BusinessServiceImpl.java @@ -42,6 +42,7 @@ import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.member.service.amount.LockManager.getStoreLock; /** * 营业统计 Service 实现类 @@ -105,7 +106,7 @@ public class BusinessServiceImpl implements BusinessService { @Override public void updateStatistics(StatisticsVo vo) { - synchronized(vo.getCarteenId()){ + synchronized(getStoreLock(vo.getCarteenId())){ // 获取今天的开始时间 LocalDateTime startOfDay = LocalDate.now().atStartOfDay(); // 获取今天的结束时间 (23:59:59.999) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/storeorder/StoreOrderServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/storeorder/StoreOrderServiceImpl.java index 2c769b0d..1fb6a618 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/storeorder/StoreOrderServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/storeorder/StoreOrderServiceImpl.java @@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.member.dal.dataobject.storeorderdetail.StoreOrder import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.dal.mysql.storeorder.StoreOrderMapper; import cn.iocoder.yudao.module.member.enums.CostTypeEnum; +import cn.iocoder.yudao.module.member.service.amount.DeductionService; import cn.iocoder.yudao.module.member.service.card.CardService; import cn.iocoder.yudao.module.member.service.storeorderdetail.StoreOrderDetailService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; @@ -59,6 +60,11 @@ public class StoreOrderServiceImpl implements StoreOrderService { @Resource private MemberUserService userService; + @Resource + private DeductionService deductionService; + + + @Override public Integer createStoreOrder(StoreOrderSaveReqVO createReqVO) { // 插入 @@ -200,45 +206,7 @@ public class StoreOrderServiceImpl implements StoreOrderService { } public BigDecimal compute(BigDecimal total, Long userId) { - //新的总价 - CardDO cardDO = new CardDO(); - cardDO.setType(CostTypeEnum.SHOPPING.getCode()); - CardDO oldCardDO = cardService.getCardDoByUserId(userId); - - - BigDecimal money = oldCardDO.getMoney(); - - if (total.compareTo(money) > 0) { - return money.subtract(total); - } - - - BigDecimal wxAmount = oldCardDO.getWxAmount(); - BigDecimal giftAmount = oldCardDO.getGiftAmount(); - BigDecimal cashAmount = oldCardDO.getCashAmount(); - cardDO.setMoney(money.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP)); - - //计算金额 - if (total.compareTo(cashAmount) <= 0) { - cardDO.setCashAmount(cashAmount.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP)); - } else { - cardDO.setCashAmount(BigDecimal.ZERO); - BigDecimal total1 = total.subtract(cashAmount).setScale(2, BigDecimal.ROUND_HALF_UP); - if (total1.compareTo(giftAmount) <= 0) { - cardDO.setGiftAmount(giftAmount.subtract(total1).setScale(2, BigDecimal.ROUND_HALF_UP)); - } else { - cardDO.setGiftAmount(BigDecimal.ZERO); - BigDecimal total2 = total1.subtract(giftAmount).setScale(2, BigDecimal.ROUND_HALF_UP); - cardDO.setWxAmount(wxAmount.subtract(total2).setScale(2, BigDecimal.ROUND_HALF_UP)); - } - } - - cardDO.setUserId(userId); - cardDO.setChangeMoney(total); - cardDO.setFlag(CardDO.MINUS); - cardService.insertOne(cardDO); - - return cardDO.getMoney(); + return deductionService.storeDeduction(total, userId); } public void test(){