热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

Java抽奖抢购算法

这篇文章主要为大家详细介绍了Java抽奖抢购算法,ava实现的抽奖抢购算法,用数据库行锁实现,支持集群,感兴趣的小伙伴们可以参考一下

本文示例为大家分享了Java抽奖抢购算法,供大家参考,具体内容如下

应用场景

单件奖品抢购(可限时)
多件奖品按概率中奖(可限时、可不限量)

代码实现

表结构:

--抽奖设置
create table AWARD_INFO
(
 ID   NUMBER(11) not null,
 ACT_ID  NUMBER(11), --活动ID
 NUM  NUMBER(11), --奖品总量(0为不限量)
 REST  NUMBER(11), --奖品余量
 ODDS  NUMBER(11) default 0, --中奖概率
 START_DATE DATE,   --开始日期(可为空)
 END_DATE DATE,   --结束日期(可为空)
 PRODUCT_ID NUMBER(11), --奖品ID
 STATE  NUMBER(5) default 0, --状态 0-有效 1-失效
 INFO_TYPE NUMBER(5) default 0  --0-正常 
);
alter table AWARD_INFO
 add constraint PK_AWARD_INFO primary key (ID);

--中奖纪录
create table AWARD_LOG
(
 id   number(11), 
 act_id  number(11), --活动ID
 get_time date, --中奖时间
 product_id number(11), --奖品ID
 num  number(11) default 1, --中奖数量
 person  varchar2(50), --中奖人
 info_id number(11), --抽奖设置ID
 state  number(5) --状态 0-有效 1-失效
);
alter table AWARD_LOG
 add constraint PK_AWARD_LOG primary key (ID);

代码:

 public static class AwardResult{
  public int ret; //返回结果
  public int logId; //AWARD_LOG id
 }

 /**
  * 抽奖算法
  * @param actId 抽奖活动ID
  * @param person 抽奖人
  * @param productId 奖品ID -1则为该活动ID下所有奖品
  * @param excludeId 排除奖品ID -1 则不排除,与productId不能同时>0
  * @param checkDate 是否检查时间
  * @return -1 没有抽奖数据;-2 奖品已抽完; -3 其他错误;>=0 中奖productId; -4 排除id
  * @throws Exception
  */
 public static AwardResult getAwardFull(int actId, String person, int productId, int[] excludeIds, boolean checkDate) throws SQLException{
  AwardResult result = new AwardResult(); 

  Connection cOnn= JDBC.getConnection();
  conn.setAutoCommit(false);
  try{
   List> rows;
   String sql;
   String checkDateStr = "";
   String baseSql = "select t.id, t.product_id, t.num, t.rest, t.odds, t.info_type from award_info t where t.act_id=? and t.state=0 ";
   if(checkDate){
    checkDateStr = " and t.start_Date <= sysdate and t.end_Date >= sysdate ";
   }
   if(productId > 0){//抢购
    sql = baseSql + " and t.product_id=&#63; " + checkDateStr + " for update";
    rows = JDBC.getRows(sql, new Object[]{actId, productId}, conn);
   }else{//活动所有物品抽奖
    sql = baseSql + checkDateStr + " for update";
    rows = JDBC.getRows(sql, new Object[]{actId}, conn);
   }

   if(rows.isEmpty()){//没有抽奖数据
    log.info("没有抽奖数据 actId={} person={} productId={} excludeIds={} checkDate={}", actId, person, productId, excludeIds, checkDate);
    conn.commit();
    result.ret = -1;
    return result;
   }
   int infoId = -1;
   int getProductId = -1;
   int num = -1;
   int rest = -1;
   if(rows.size() == 1){//抢购
    num = ((Number)rows.get(0).get("NUM")).intValue();
    rest = ((Number)rows.get(0).get("REST")).intValue();
    infoId = ((Number)rows.get(0).get("ID")).intValue();
    getProductId = ((Number)rows.get(0).get("PRODUCT_ID")).intValue();
   }else{//抽奖
    int[][] temp = new int[rows.size()][3];
    int sum = -1;
    int i = 0;
    for(int k = 0; k = temp[k][0] && r <= temp[k][1]){
      j = k;
      break;
     }
    }
    infoId = ((BigDecimal)rows.get(temp[j][2]).get("ID")).intValue();
    getProductId = ((BigDecimal)rows.get(temp[j][2]).get("PRODUCT_ID")).intValue();
    num = ((Number)rows.get(temp[j][2]).get("NUM")).intValue();
    rest = ((Number)rows.get(temp[j][2]).get("REST")).intValue();
   }

   //判断是否排除id
   if(ArrayUtils.contains(excludeIds, getProductId)){
    log.info("是排除ID actId={} person={} productId={} excludeIds={} checkDate={}", actId, person, productId, excludeIds, checkDate);
    conn.commit();
    result.ret = -4;
    return result;
   }

   //存量不足
   if(num > 0 && rest <= 0){
    log.info("奖品已清空 actId={} person={} productId={} excludeIds={} checkDate={}", actId, person, productId, excludeIds, checkDate);
    JDBC.commit(conn);
    result.ret = -2;
    return result;
   }

   //更新奖品记录
   if(num > 0){//非不限量
    sql = "update award_info set rest = rest - 1 where id = &#63;";
    JDBC.update(sql, new Object[]{infoId}, conn);
   }

   //记录获奖名单
   AwardLog log = new AwardLog();
   log.setActId(actId);
   log.setNum(1);
   log.setPerson(person);
   log.setProductId(getProductId);
   log.setInfoId(infoId);
   Number logId = log.save(conn);
   if(logId == null){
    throw new SQLException("save award_log error");
   }
   result.logId = logId.intValue();

   conn.commit();
   result.ret = getProductId;
   return result;

  }catch(SQLException e){
   log.error("getAward error", e);
   conn.rollback();
  }finally{
   JDBC.close(conn);
  }
  result.ret = -3;
  return result;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
author-avatar
大米的感悟_673
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有