Skip to content

Instantly share code, notes, and snippets.

@zhugw
Created August 6, 2016 11:23
Show Gist options
  • Save zhugw/0852f5f0ee38f07a8661d0e57db1853e to your computer and use it in GitHub Desktop.
Save zhugw/0852f5f0ee38f07a8661d0e57db1853e to your computer and use it in GitHub Desktop.
多线程模拟并发抽奖中礼帽和兑奖
package com.zhugw;
import org.apache.commons.lang3.RandomStringUtils;
import java.sql.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by duanmu on 8/6/16.
*/
public class ConcurrentUpdateTotalAmountTest {
public static final String url = "jdbc:mysql://localhost:3306/test";
public static final String user = "root";
public static final String password = "12345678";
public static void main(String[] args) throws InterruptedException, SQLException {
int nThreads = 6; //6个线程 3个抽奖 3个兑奖
ExecutorService pool = Executors.newFixedThreadPool(nThreads);
final CountDownLatch startLatch = new CountDownLatch(nThreads);
final CountDownLatch endLatch = new CountDownLatch(nThreads);
String mobile = RandomStringUtils.randomNumeric(11);
initData(mobile); //数据初始化 默认当前总礼帽为3
// 模拟3个抽奖 每次都中了1个礼帽 total_amount+1
for (int i = 0; i < 3; i++) {
pool.submit(() -> {
startLatch.countDown();
try { startLatch.await(); } catch (Exception e1) { } //等待所有任务都提交了再往下执行 保证并发
try {
Connection connection = DriverManager.getConnection(url, user, password);
connection.setAutoCommit(false);
Statement stat = connection.createStatement();
// 添加中奖日志
String insertSql = "insert into user_draw_log(mobile,amount) values('%s',1)";
stat.execute(String.format(insertSql, mobile));
// 更新总礼帽数
String updateSql = "update user_draw_info set total_amount = total_amount+1 where mobile = '%s'";
stat.executeUpdate(String.format(updateSql, mobile));
System.out.printf("mobile: %s中小礼帽成功更新总礼帽数%n",mobile);
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}finally{
endLatch.countDown();
}
});
}
// 模拟3个兑奖操作 total_amount=0
for (int i = 0; i < 3; i++) {
pool.submit(() -> {
startLatch.countDown();
try { startLatch.await(); } catch (Exception e1) { } //等待所有任务都提交了再往下执行 保证并发
try {
Connection connection = DriverManager.getConnection(url, user, password);
connection.setAutoCommit(false);
Statement stat = connection.createStatement();
// 先查询出累积礼帽
String queryTotalAmountSql = "select total_amount from user_draw_info where mobile = '%s'";
ResultSet resultSet = stat.executeQuery(String.format(queryTotalAmountSql, mobile));
resultSet.next();
int totalAmount = resultSet.getInt("total_amount");
if(totalAmount>0) { // 若累积礼帽大于0
// 礼帽清零
String resetSql = "update user_draw_info set total_amount = 0 where mobile='%s' and total_amount=%d";
int count = stat.executeUpdate(String.format(resetSql, mobile,totalAmount));
if(count>0){ // 礼帽清零成功
// 模拟发券
String insertSql = "insert user_redeem_log (mobile,redeem_amount) values('%s',%d)";
stat.execute(String.format(insertSql, mobile,totalAmount));
System.out.printf("mobile: %s 成功兑券: %d%n",mobile,totalAmount);
}else{System.out.printf("mobile: %s 礼帽清零失败%n",mobile);}
}
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}finally{
endLatch.countDown();
}
});
}
endLatch.await(); //等待所有的任务都完成
System.out.println("Done");
System.exit(0);
}
private static void initData(String mobile) throws SQLException {
Connection connection = DriverManager.getConnection(url, user, password);
Statement stat = connection.createStatement();
String sql = "insert into user_draw_info(mobile,total_amount) values('%s',3)";
stat.execute(String.format(sql, mobile));
System.out.println("数据初始化完成");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment