当前位置:首页 > 算法 > 正文内容

MySQL悲观锁 select for update实现秒杀案例(jfinal框架)

canca6年前 (2020-03-31)算法501

为了方便测试,博主使用最新的jfinal框架,里边的东西就修改了一下a_little_config.txt,配置数据库链接的,启动直接打开DemoConfig.java,main方法启动即可(记得修改端口),这样就不用再去写jdbc了。感兴趣的朋友可以去了解一下:


主要源码(模拟120人同时抢购100件商品):

package com.demo.index;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import com.jfinal.core.Controller;
import com.jfinal.plugin.activerecord.Db;
 
/**
 * 秒杀/MySQL 悲观锁实现方式
 * 
 * @author sun
 */
public class SecKillForPLController extends Controller {
     
    public static int goodsTotalNum = 100;
 
    public void index() {
        //每一次新的请求都会模拟抢购100件商品,所以先恢复商品的数量,这个可以不要,也可以手动去更新数据库
        Db.update("update t_goods set num = ? where id = 1", goodsTotalNum);
         
        SecKillPL sk = new SecKillPL();
        // 模拟120个人抢购
        for (int i = 1; i <= 120; i++) {
            new Thread(sk, i + " 号人").start();
        }
        renderHtml("<center><h2>抢购成功!</h2></center>");
    }
}
 
/**
 * 这里我们只是演示数据库悲观锁的实现方式,至于事务等其他的都不添加了。
 * 
 * @author sun
 */
class SecKillPL implements Runnable {
 
    @Override
    public void run() {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = Db.use().getConfig().getConnection();
            conn.setAutoCommit(false);
            ps = conn.prepareStatement("select * from t_goods where id = 1 for update");
            ResultSet rs = ps.executeQuery();
            Integer num = 0;
            while (rs.next()) {
                num = rs.getInt("num");
            }
            if (num > 0) {
                PreparedStatement ps2 = conn.prepareStatement("update t_goods set num=num-1 where id = 1");
                ps2.execute();
                System.out.println(Thread.currentThread().getName() + " 抢到了第" + (SecKillForPLController.goodsTotalNum - num + 1) + "商品");
                conn.commit();
            }else{
                System.err.println(Thread.currentThread().getName() + " 太悲剧了,没抢到商品...");
            }
        } catch (SQLException e1) {
            e1.printStackTrace();
        } finally {
            try {
                ps.close();
            } catch (SQLException e) {}
            try {
                conn.close();
            } catch (SQLException e) {}
        }
    }
}

代码里有些jfinal的东西,看不懂的不要紧,只要知道是操作sql就行。

输出结果:

3 号人 抢到了第1商品
2 号人 抢到了第2商品
1 号人 抢到了第3商品
4 号人 抢到了第4商品
9 号人 抢到了第5商品
6 号人 抢到了第6商品
5 号人 抢到了第7商品
......
95 号人 抢到了第92商品
94 号人 抢到了第93商品
97 号人 抢到了第94商品
98 号人 抢到了第95商品
99 号人 抢到了第96商品
100 号人 抢到了第97商品
80 号人 抢到了第98商品
83 号人 抢到了第99商品
102 号人 抢到了第100商品
96 号人 太悲剧了,没抢到商品...
101 号人 太悲剧了,没抢到商品...
103 号人 太悲剧了,没抢到商品...
104 号人 太悲剧了,没抢到商品...
105 号人 太悲剧了,没抢到商品...
106 号人 太悲剧了,没抢到商品...
107 号人 太悲剧了,没抢到商品...
108 号人 太悲剧了,没抢到商品...
109 号人 太悲剧了,没抢到商品...
110 号人 太悲剧了,没抢到商品...
111 号人 太悲剧了,没抢到商品...
112 号人 太悲剧了,没抢到商品...
113 号人 太悲剧了,没抢到商品...
114 号人 太悲剧了,没抢到商品...
115 号人 太悲剧了,没抢到商品...
116 号人 太悲剧了,没抢到商品...
117 号人 太悲剧了,没抢到商品...
118 号人 太悲剧了,没抢到商品...
119 号人 太悲剧了,没抢到商品...
120 号人 太悲剧了,没抢到商品...

t_goods表结构:

CREATE TABLE `d_sunjs_test`.`t_goods`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `num` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;


扫描二维码推送至手机访问。

版权声明:本文由Ant.Master's Blog发布,如需转载请注明出处。

本文链接:https://iant.work/post/704.html

标签: 算法
分享给朋友:

“MySQL悲观锁 select for update实现秒杀案例(jfinal框架)” 的相关文章

jfinal 乐观锁

继承Model类,实现自己的BaseModel,重写save()和update()方法,然后所有的Model都继承自BaseModel /**   * 重写save方法   */  public boolean&n...

不同概率的抽奖

需求很简单,为了更加形象,这里我们列一个表格来显示我们抽奖的物品和对应的概率(没有边框,大家凑合着看看吧,不想改造Octopress的样式了)序号物品名称物品ID抽奖概率1物品1P10.22物品2P20.13物品3P30.44物品4P40.35物品5P50.06物品6P6-0.17物品7P70.00...

MySQL Redis分布式锁实现秒杀案例(jfinal框架)

我们加锁就一行代码:jedis.set(String key, String value, String nxxx, String expx, int time),这个set()方法一共有五个形参:    第一个为key,我们使用key来当锁,因为key是唯一...

zookeeper分布式锁实现秒杀案例(jfinal框架)

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的架构通过冗余服务实现高可用性。...

MySQL乐观锁 实现秒杀案例,增加version字段来判断(jfinal框架)

MySQL乐观锁和悲观锁的主要区别在于:悲观锁在查询的时候就认为别人会和我抢,我查询的时候就先锁起来。乐观锁在查询的时候认为别人不会和我抢,我在更新的时候判断一下就可以了。所以如果在高并发的情况下,博主认为乐观锁并不适合做这种业务,因为是先查询,导致数据库有很多的更新失败,处理异常再次执行的情况,相...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。