Java抽獎(jiǎng)?chuàng)屬徦惴?/h1>
更新時(shí)間:2020年04月15日 15:28:48 作者:天藍(lán)1122
這篇文章主要為大家詳細(xì)介紹了Java抽獎(jiǎng)?chuàng)屬徦惴?ava實(shí)現(xiàn)的抽獎(jiǎng)?chuàng)屬徦惴?,用?shù)據(jù)庫行鎖實(shí)現(xiàn),支持集群,感興趣的小伙伴們可以參考一下
本文示例為大家分享了Java抽獎(jiǎng)?chuàng)屬徦惴?,供大家參考,具體內(nèi)容如下
應(yīng)用場景
單件獎(jiǎng)品搶購(可限時(shí))
多件獎(jiǎng)品按概率中獎(jiǎng)(可限時(shí)、可不限量)
代碼實(shí)現(xiàn)
表結(jié)構(gòu):
--抽獎(jiǎng)設(shè)置
create table AWARD_INFO
(
ID NUMBER(11) not null,
ACT_ID NUMBER(11), --活動(dòng)ID
NUM NUMBER(11), --獎(jiǎng)品總量(0為不限量)
REST NUMBER(11), --獎(jiǎng)品余量
ODDS NUMBER(11) default 0, --中獎(jiǎng)概率
START_DATE DATE, --開始日期(可為空)
END_DATE DATE, --結(jié)束日期(可為空)
PRODUCT_ID NUMBER(11), --獎(jiǎng)品ID
STATE NUMBER(5) default 0, --狀態(tài) 0-有效 1-失效
INFO_TYPE NUMBER(5) default 0 --0-正常
);
alter table AWARD_INFO
add constraint PK_AWARD_INFO primary key (ID);
--中獎(jiǎng)紀(jì)錄
create table AWARD_LOG
(
id number(11),
act_id number(11), --活動(dòng)ID
get_time date, --中獎(jiǎng)時(shí)間
product_id number(11), --獎(jiǎng)品ID
num number(11) default 1, --中獎(jiǎng)數(shù)量
person varchar2(50), --中獎(jiǎng)人
info_id number(11), --抽獎(jiǎng)設(shè)置ID
state number(5) --狀態(tài) 0-有效 1-失效
);
alter table AWARD_LOG
add constraint PK_AWARD_LOG primary key (ID);
代碼:
public static class AwardResult{
public int ret; //返回結(jié)果
public int logId; //AWARD_LOG id
}
/**
* 抽獎(jiǎng)算法
* @param actId 抽獎(jiǎng)活動(dòng)ID
* @param person 抽獎(jiǎng)人
* @param productId 獎(jiǎng)品ID -1則為該活動(dòng)ID下所有獎(jiǎng)品
* @param excludeId 排除獎(jiǎng)品ID -1 則不排除,與productId不能同時(shí)>0
* @param checkDate 是否檢查時(shí)間
* @return -1 沒有抽獎(jiǎng)數(shù)據(jù);-2 獎(jiǎng)品已抽完; -3 其他錯(cuò)誤;>=0 中獎(jiǎng)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<Map<String,Object>> 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=? " + checkDateStr + " for update";
rows = JDBC.getRows(sql, new Object[]{actId, productId}, conn);
}else{//活動(dòng)所有物品抽獎(jiǎng)
sql = baseSql + checkDateStr + " for update";
rows = JDBC.getRows(sql, new Object[]{actId}, conn);
}
if(rows.isEmpty()){//沒有抽獎(jiǎng)數(shù)據(jù)
log.info("沒有抽獎(jiǎng)數(shù)據(jù) 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{//抽獎(jiǎng)
int[][] temp = new int[rows.size()][3];
int sum = -1;
int i = 0;
for(int k = 0; k < rows.size(); k++){//設(shè)置獎(jiǎng)品池
int odds = ((BigDecimal)rows.get(k).get("ODDS")).intValue();
sum++;
temp[i][0] = sum; //起始值
sum = sum + odds;
temp[i][1] = sum; //結(jié)束值
temp[i][2] = k; //rows index
i++;
}
//抽獎(jiǎng)
Random random = new Random();
int r = random.nextInt(sum + 1);
int j = 0;
for(int k = 0; k < i; k++){
if(r >= 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("獎(jiǎng)品已清空 actId={} person={} productId={} excludeIds={} checkDate={}", actId, person, productId, excludeIds, checkDate);
JDBC.commit(conn);
result.ret = -2;
return result;
}
//更新獎(jiǎng)品記錄
if(num > 0){//非不限量
sql = "update award_info set rest = rest - 1 where id = ?";
JDBC.update(sql, new Object[]{infoId}, conn);
}
//記錄獲獎(jiǎng)名單
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;
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:- 基于Java實(shí)現(xiàn)抽獎(jiǎng)系統(tǒng)
- 簡單實(shí)現(xiàn)java抽獎(jiǎng)系統(tǒng)
- 純java代碼實(shí)現(xiàn)抽獎(jiǎng)系統(tǒng)
- Java抽獎(jiǎng)算法第二例
- Java實(shí)現(xiàn)雙色球抽獎(jiǎng)隨機(jī)算法示例
- Java簡易抽獎(jiǎng)系統(tǒng)小項(xiàng)目
- JAVA實(shí)現(xiàn)用戶抽獎(jiǎng)功能(附完整代碼)
- java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)系統(tǒng)
- JAVA使用隨機(jī)數(shù)實(shí)現(xiàn)概率抽獎(jiǎng)
- Java使用HashMap映射實(shí)現(xiàn)消費(fèi)抽獎(jiǎng)功能
相關(guān)文章
-
java中兩個(gè)字符串的拼接、整數(shù)相加和浮點(diǎn)數(shù)相加實(shí)現(xiàn)代碼
這篇文章主要為大家介紹java中從鍵盤讀取用戶輸入兩個(gè)字符串,實(shí)現(xiàn)這兩個(gè)字符串的拼接、整數(shù)相加和浮點(diǎn)數(shù)相加,并輸出結(jié)果,需要的朋友可以參考下 2021-05-05
-
修改Maven settings.xml 后配置未生效的解決
這篇文章主要介紹了修改Maven settings.xml 后配置未生效的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧 2020-10-10
-
關(guān)于@MapperScan和@ComponentScan的使用問題
文章介紹了在使用`@MapperScan`和`@ComponentScan`時(shí)可能會(huì)遇到的包掃描沖突問題,并提供了解決方法,同時(shí),還詳細(xì)解釋了`@MapperScan`和`@ComponentScan`的功能和使用場景 2025-01-01
-
Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用
這篇文章主要介紹了Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下 2020-01-01
-
Springboot Cache @CacheEvict 無法模糊刪除的解決方案
這篇文章主要介紹了Springboot Cache @CacheEvict 無法模糊刪除的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2021-12-12
-
關(guān)于Java應(yīng)用日志與Jaeger的trace關(guān)聯(lián)的問題
這篇文章主要介紹了Java應(yīng)用日志如何與Jaeger的trace關(guān)聯(lián),通過jaeger發(fā)現(xiàn)這十次請(qǐng)求中有一次耗時(shí)特別長,想定位一下具體原因,感興趣的朋友跟隨小編一起看看吧 2022-01-01
-
解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個(gè)文件無法傳輸多個(gè)問題
這篇文章主要介紹了解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個(gè)文件無法傳輸多個(gè)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2024-08-08
最新評(píng)論
本文示例為大家分享了Java抽獎(jiǎng)?chuàng)屬徦惴?,供大家參考,具體內(nèi)容如下
應(yīng)用場景
單件獎(jiǎng)品搶購(可限時(shí))
多件獎(jiǎng)品按概率中獎(jiǎng)(可限時(shí)、可不限量)
代碼實(shí)現(xiàn)
表結(jié)構(gòu):
--抽獎(jiǎng)設(shè)置 create table AWARD_INFO ( ID NUMBER(11) not null, ACT_ID NUMBER(11), --活動(dòng)ID NUM NUMBER(11), --獎(jiǎng)品總量(0為不限量) REST NUMBER(11), --獎(jiǎng)品余量 ODDS NUMBER(11) default 0, --中獎(jiǎng)概率 START_DATE DATE, --開始日期(可為空) END_DATE DATE, --結(jié)束日期(可為空) PRODUCT_ID NUMBER(11), --獎(jiǎng)品ID STATE NUMBER(5) default 0, --狀態(tài) 0-有效 1-失效 INFO_TYPE NUMBER(5) default 0 --0-正常 ); alter table AWARD_INFO add constraint PK_AWARD_INFO primary key (ID); --中獎(jiǎng)紀(jì)錄 create table AWARD_LOG ( id number(11), act_id number(11), --活動(dòng)ID get_time date, --中獎(jiǎng)時(shí)間 product_id number(11), --獎(jiǎng)品ID num number(11) default 1, --中獎(jiǎng)數(shù)量 person varchar2(50), --中獎(jiǎng)人 info_id number(11), --抽獎(jiǎng)設(shè)置ID state number(5) --狀態(tài) 0-有效 1-失效 ); alter table AWARD_LOG add constraint PK_AWARD_LOG primary key (ID);
代碼:
public static class AwardResult{
public int ret; //返回結(jié)果
public int logId; //AWARD_LOG id
}
/**
* 抽獎(jiǎng)算法
* @param actId 抽獎(jiǎng)活動(dòng)ID
* @param person 抽獎(jiǎng)人
* @param productId 獎(jiǎng)品ID -1則為該活動(dòng)ID下所有獎(jiǎng)品
* @param excludeId 排除獎(jiǎng)品ID -1 則不排除,與productId不能同時(shí)>0
* @param checkDate 是否檢查時(shí)間
* @return -1 沒有抽獎(jiǎng)數(shù)據(jù);-2 獎(jiǎng)品已抽完; -3 其他錯(cuò)誤;>=0 中獎(jiǎng)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<Map<String,Object>> 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=? " + checkDateStr + " for update";
rows = JDBC.getRows(sql, new Object[]{actId, productId}, conn);
}else{//活動(dòng)所有物品抽獎(jiǎng)
sql = baseSql + checkDateStr + " for update";
rows = JDBC.getRows(sql, new Object[]{actId}, conn);
}
if(rows.isEmpty()){//沒有抽獎(jiǎng)數(shù)據(jù)
log.info("沒有抽獎(jiǎng)數(shù)據(jù) 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{//抽獎(jiǎng)
int[][] temp = new int[rows.size()][3];
int sum = -1;
int i = 0;
for(int k = 0; k < rows.size(); k++){//設(shè)置獎(jiǎng)品池
int odds = ((BigDecimal)rows.get(k).get("ODDS")).intValue();
sum++;
temp[i][0] = sum; //起始值
sum = sum + odds;
temp[i][1] = sum; //結(jié)束值
temp[i][2] = k; //rows index
i++;
}
//抽獎(jiǎng)
Random random = new Random();
int r = random.nextInt(sum + 1);
int j = 0;
for(int k = 0; k < i; k++){
if(r >= 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("獎(jiǎng)品已清空 actId={} person={} productId={} excludeIds={} checkDate={}", actId, person, productId, excludeIds, checkDate);
JDBC.commit(conn);
result.ret = -2;
return result;
}
//更新獎(jiǎng)品記錄
if(num > 0){//非不限量
sql = "update award_info set rest = rest - 1 where id = ?";
JDBC.update(sql, new Object[]{infoId}, conn);
}
//記錄獲獎(jiǎng)名單
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;
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 基于Java實(shí)現(xiàn)抽獎(jiǎng)系統(tǒng)
- 簡單實(shí)現(xiàn)java抽獎(jiǎng)系統(tǒng)
- 純java代碼實(shí)現(xiàn)抽獎(jiǎng)系統(tǒng)
- Java抽獎(jiǎng)算法第二例
- Java實(shí)現(xiàn)雙色球抽獎(jiǎng)隨機(jī)算法示例
- Java簡易抽獎(jiǎng)系統(tǒng)小項(xiàng)目
- JAVA實(shí)現(xiàn)用戶抽獎(jiǎng)功能(附完整代碼)
- java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)系統(tǒng)
- JAVA使用隨機(jī)數(shù)實(shí)現(xiàn)概率抽獎(jiǎng)
- Java使用HashMap映射實(shí)現(xiàn)消費(fèi)抽獎(jiǎng)功能
相關(guān)文章
java中兩個(gè)字符串的拼接、整數(shù)相加和浮點(diǎn)數(shù)相加實(shí)現(xiàn)代碼
這篇文章主要為大家介紹java中從鍵盤讀取用戶輸入兩個(gè)字符串,實(shí)現(xiàn)這兩個(gè)字符串的拼接、整數(shù)相加和浮點(diǎn)數(shù)相加,并輸出結(jié)果,需要的朋友可以參考下2021-05-05
修改Maven settings.xml 后配置未生效的解決
這篇文章主要介紹了修改Maven settings.xml 后配置未生效的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10
關(guān)于@MapperScan和@ComponentScan的使用問題
文章介紹了在使用`@MapperScan`和`@ComponentScan`時(shí)可能會(huì)遇到的包掃描沖突問題,并提供了解決方法,同時(shí),還詳細(xì)解釋了`@MapperScan`和`@ComponentScan`的功能和使用場景2025-01-01
Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用
這篇文章主要介紹了Spring @async方法如何添加注解實(shí)現(xiàn)異步調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
Springboot Cache @CacheEvict 無法模糊刪除的解決方案
這篇文章主要介紹了Springboot Cache @CacheEvict 無法模糊刪除的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
關(guān)于Java應(yīng)用日志與Jaeger的trace關(guān)聯(lián)的問題
這篇文章主要介紹了Java應(yīng)用日志如何與Jaeger的trace關(guān)聯(lián),通過jaeger發(fā)現(xiàn)這十次請(qǐng)求中有一次耗時(shí)特別長,想定位一下具體原因,感興趣的朋友跟隨小編一起看看吧2022-01-01
解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個(gè)文件無法傳輸多個(gè)問題
這篇文章主要介紹了解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個(gè)文件無法傳輸多個(gè)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

