java减库存代码_模拟实现一个秒杀减库存的案例

需求:

对商品秒杀,每个用户只能对一个商品买一次

实现思路:

设计三个表,商品详情表,商品总数表,用户订单表

插入订单表和更新总数表放到一个事务里边,更新j库存总数时,受影响行数小于等于0的时候,事务回滚;

对订单表的(user_id,goods_id)加唯一索引,一个用户只能买一笔商品,如果插入的时候报错,事务回滚;

//开启事务

//更新库存数量

update goods set goods_num=goods_num-1  where goods_id=$goods_id and goods_num>0 ;

if(受影响行数<=0)

抛异常,商品秒完了,回滚。。。

//插入订单

insert into goods_order。。。

if(唯一索引报错?)

抛异常,已经秒过了,回滚。。。

//最后提交事务

数据库设计:

商品详情表:

DROP TABLE IF EXISTS `goods`;

CREATE TABLE `goods` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',

`goods_name` varchar(50) NOT NULL,

`add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='商品详情表';

-- ----------------------------

-- Records of goods

-- ----------------------------

INSERT INTO `goods` VALUES ('1', '笔记本', '2016-04-27 10:24:48');

商品总数表:

DROP TABLE IF EXISTS `goods_num`;

CREATE TABLE `goods_num` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`goods_id` int(11) NOT NULL COMMENT '货品ID',

`goods_num` int(11) NOT NULL COMMENT '商品总数',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='商品总数表';

-- ----------------------------

-- Records of goods_num

-- ----------------------------

INSERT INTO `goods_num` VALUES ('1', '1', '3');

用户订单表:

DROP TABLE IF EXISTS `goods_order`;

CREATE TABLE `goods_order` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '订单ID',

`goods_id` int(11) NOT NULL COMMENT '商品ID',

`user_id` int(11) NOT NULL COMMENT '用户ID',

PRIMARY KEY (`id`),

UNIQUE KEY `good_user` (`goods_id`,`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=409 DEFAULT CHARSET=utf8 COMMENT='订单表';

具体实现代码:

package class10;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class SnapUp {

/**

*

* 功能说明:数据库连接

*

* @return

*

*/

private static Connection getConn() {

String driver = "com.mysql.jdbc.Driver";

String url = "jdbc:mysql://localhost:3306/study";

String username = "root";

String password = "123456";

Connection conn = null;

try {

Class.forName(driver); //classLoader,加载对应驱动

conn = (Connection) DriverManager.getConnection(url, username, password);

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

return conn;

}

/**

* 功能说明:秒杀抢购

* @param goodsId 商品ID

* @param userId 用户ID

*

*/

public static void snapUp(int goodsId, int userId) {

Connection conn = getConn();

Statement stmt = null;

PreparedStatement pst = null;

try {

stmt = conn.createStatement();

//首先,.设置事务的提交方式为非自动提交

conn.setAutoCommit(false);

//更新库存

String sqlUpdate = "update goods_num set goods_num=goods_num-1 where goods_id=" + goodsId

+ " and goods_num>0";

pst = conn.prepareStatement(sqlUpdate);

int count = pst.executeUpdate();

if (count <= 0) {

System.out.println("货物已经被抢空了,明天再来吧");

throw new RuntimeException();

}

// 插入订单

String sqlOrder = "insert into goods_order(goods_id,user_id)values(?,?)";

pst = conn.prepareStatement(sqlOrder);

pst.setInt(1, goodsId);

pst.setInt(2, userId);

pst.executeUpdate();

System.out.println("用户:" + userId + "抢购货物:" + goodsId + "成功!");

conn.commit();

} catch (Exception e) {

System.out.println("用户:" + userId + "抢购货物:" + goodsId + "失败!");

try {

//.在catch块内添加回滚事务,表示操作出现异常,撤销事务:

conn.rollback();

} catch (SQLException e1) {

//e1.printStackTrace();

}

//e.printStackTrace();

} finally {

try {

//设置事务提交方式为自动提交

conn.setAutoCommit(true);

stmt.close();

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

public static void main(String[] args) {

// 线程池

ExecutorService exec = Executors.newCachedThreadPool();

// 模拟50个客户端访问

for (int index = 0; index 

final int userId = index / 9;

Runnable run = new Runnable() {

public void run() {

snapUp(1, userId);

}

};

exec.execute(run);

}

// 退出线程池

exec.shutdown();

}

}

结果:

用户:4抢购货物:1成功!

用户:3抢购货物:1成功!

用户:1抢购货物:1成功!

用户:5抢购货物:1失败!

用户:5抢购货物:1失败!

用户:3抢购货物:1失败!

用户:1抢购货物:1失败!

用户:1抢购货物:1失败!

用户:4抢购货物:1失败!

用户:3抢购货物:1失败!

用户:1抢购货物:1失败!

用户:1抢购货物:1失败!

用户:1抢购货物:1失败!

用户:3抢购货物:1失败!

用户:1抢购货物:1失败!

用户:1抢购货物:1失败!

用户:3抢购货物:1失败!

用户:3抢购货物:1失败!

用户:3抢购货物:1失败!

用户:4抢购货物:1失败!

用户:1抢购货物:1失败!

用户:4抢购货物:1失败!

用户:3抢购货物:1失败!

用户:4抢购货物:1失败!

用户:3抢购货物:1失败!

用户:4抢购货物:1失败!

用户:4抢购货物:1失败!

用户:4抢购货物:1失败!

用户:0抢购货物:1失败!

用户:4抢购货物:1失败!

用户:2抢购货物:1失败!

用户:2抢购货物:1失败!

用户:0抢购货物:1失败!

用户:2抢购货物:1失败!

用户:0抢购货物:1失败!

用户:2抢购货物:1失败!

用户:0抢购货物:1失败!

用户:2抢购货物:1失败!

用户:0抢购货物:1失败!

用户:0抢购货物:1失败!

用户:2抢购货物:1失败!

用户:0抢购货物:1失败!

用户:0抢购货物:1失败!

用户:0抢购货物:1失败!

用户:2抢购货物:1失败!

用户:2抢购货物:1失败!

用户:2抢购货物:1失败!

用户:5抢购货物:1失败!

用户:5抢购货物:1失败!

用户:5抢购货物:1失败!

最后查看goods_num表,总数变为0, goods_order里边有3条不重复的用户订单记录,说明只有独立的三个人抢购成功。

借鉴了http://www.tuicool.com/articles/Bfa63e6

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值