砍价并发问题解决

*解决并发问题的关键在于找到一把共同的锁:

将锁声明为static 保存多个线程访问到同一把锁,把业务中要用到的参数进行加锁获取,保证每次拿到都是最新值,controller是单例和多例都没关系,最好还是用多例,但是锁必须为静态属性,如何是单例,可以是普通属性和静态属性都行,只要保证锁的唯一性就行。

下面附带测试案例,自己根据业务需求灵活运用:

加微信 aa544731152 交流你们遇到的并发问题,随时帮你们解决


@Controller
@RequestMapping("/kan")
@Scope(value="singleton")
public class KanBarginController extends BaseClass{
    
    private static ReentrantLock lock = new ReentrantLock();
    /**
     * 点击砍价的接口
     */
    @RequestMapping(value = "/helpBargain")
    @ResponseBody
    public JSONObject helpBargain(final ModelMap model,HttpServletRequest request, HttpServletResponse response) {
        JSONObject res = new JSONObject();
        RedisImpl redis =new RedisImpl();
        String orderId = request.getParameter("orderId");
        String appId = "wx855d106b81a13845";
        String helpPersonOpenId =request.getParameter("helpPersonOpenId"); 
        Map map = productBargainService.queryZyzsFansInfo(helpPersonOpenId);
        if(map == null) {
            redis.delKey(orderId);
            res.put("code", "0001");
            res.put("msg","关注后才可帮助好友砍价奥~");
            return res;
        }
        //帮忙砍价人的openId
        Map<String,Object> record =  productBargainService.queryOrderAndTask(orderId);
        //发起人的openId
        try {
            lock.lock();
            Kan kan = redis.getObj(orderId, Kan.class);
            if(null == kan) {
                redis.delKey(orderId);
                res.put("code", "0001");
                res.put("msg","已砍到最低价,不能再砍了!");
                return res;
            }
            //1.自己不可以自己砍价
            if(kan.getOpenId().equals(helpPersonOpenId)){
                res.put("code", "0001");
                res.put("msg","自己不能帮自己砍价");
                return res;
            }
            //2.查询是否砍过
            Map hasBargain=productBargainService.queryCopyHelper(helpPersonOpenId, orderId);
            if(hasBargain!=null){
                res.put("code", "0001");
                res.put("msg","已经砍过");
                return res;
            }
            if(kan.getNum()==0){
                redis.delKey(orderId);
                res.put("code", "0001");
                res.put("msg","砍价人数已达上线~");
                return res;
            }
            
            BigDecimal coin = randoncoin(new BigDecimal(kan.getNum()),kan.getLeftmoney(), kan.getMinCoin());
            kan.setLeftmoney(kan.getLeftmoney().subtract(coin));
            kan.setNum(kan.getNum()-1);
            redis.setObj(orderId, kan, 3600*24);
            res  = productBargainService.help(coin,orderId,helpPersonOpenId);
        } catch (Exception e) {
        }finally{
            lock.unlock();
        }
        return res;
    }
    
    
    /**
     * 随机砍价算法
     */
    public BigDecimal randoncoin(BigDecimal num , BigDecimal leftmoney,BigDecimal minCoin){
        lock.lock();
        BigDecimal money=new BigDecimal(0);
        try {
            if(num.intValue() == 1) {
                 return leftmoney;
            }
            
            BigDecimal max   = leftmoney.divide(num,2, BigDecimal.ROUND_HALF_DOWN).multiply(new BigDecimal(2));
            Double next= Math.random() * max.intValue();
            
            money  = new BigDecimal(next).divide(new BigDecimal(1),2, BigDecimal.ROUND_HALF_DOWN);
            money = money.compareTo(minCoin)<0 ? minCoin : money;
            return money;
        } catch (Exception e) {
            // TODO: handle exception
        }finally{
            lock.unlock();
        }
        
        return money;
    }
}

测试案例

	
	public static void test01(){
		ExecutorService service = Executors.newCachedThreadPool();
		final CountDownLatch latch = new CountDownLatch(2);
		for(int i=0;i<2;i++){
			final int j = i;
			Runnable runnable = new Runnable(){
					public void run(){
					try {
						String url = "http://127.0.0.1/zyzsSd/kan/helpBargain";
						String param="";
						if(j%2==0){
							
							param="orderId=40284e8166c7c8870166c7cc8ebe0000&helpPersonOpenId="+j;
						}else{
							param="orderId=40284e8166c7c8870166c7cc8ebe0000&helpPersonOpenId="+j;
						}
						System.out.println(HttpUtil.sendGet(url, param));
						latch.countDown();
					} catch (Exception e) {
						e.printStackTrace();
					}
					
				}
			};
			service.execute(runnable);
		}		
		try {
			latch.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		service.shutdown();
	}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值