欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何防止秒杀抢购超卖?

程序员文章站 2022-03-30 17:53:27
可以利用redis的事务加上watch监听方法,具体代码如下! ......

可以利用redis的事务加上watch监听方法,具体代码如下!

  1 package com.github.distribute.lock.redis;
  2 
  3 import java.util.list;
  4 import java.util.set;
  5 import java.util.concurrent.executorservice;
  6 import java.util.concurrent.executors;
  7 
  8 import redis.clients.jedis.jedis;
  9 import redis.clients.jedis.transaction;
 10 
 11 /**
 12  * redis乐观锁实例
 13  * @author linbingwen
 14  *
 15  */
 16 public class optimisticlocktest {
 17 
 18     public static void main(string[] args) throws interruptedexception {
 19         long startime=system.currenttimemillis();
 20 
 21         initprduct();
 22         initclient();
 23         printresult();
 24 
 25         long endtime=system.currenttimemillis();
 26         long time=endtime-startime;
 27         system.out.println("程序运行时间: "+time+"ms");
 28 
 29     }
 30 
 31     /**
 32      * 输出结果
 33      */
 34     public static void printresult() {
 35         jedis jedis = redisutil.getinstance().getjedis();
 36         set<string> set = jedis.smembers("clientlist");
 37 
 38         int i = 1;
 39         for (string value : set) {
 40             system.out.println("第" + i++ + "个抢到商品,"+value + " ");
 41         }
 42 
 43         redisutil.returnresource(jedis);
 44     }
 45 
 46     /*
 47      * 初始化顾客开始抢商品
 48      */
 49     public static void initclient() {
 50         executorservice cachedthreadpool = executors.newcachedthreadpool();
 51         int clientnum = 10000;// 模拟客户数目
 52         for (int i = 0; i < clientnum; i++) {
 53             cachedthreadpool.execute(new clientthread(i));
 54         }
 55         cachedthreadpool.shutdown();
 56 
 57         while(true){
 58             if(cachedthreadpool.isterminated()){
 59                 system.out.println("所有的线程都结束了!");
 60                 break;
 61             }
 62             try {
 63                 thread.sleep(1000);
 64             } catch (interruptedexception e) {
 65                 e.printstacktrace();
 66             }
 67         }
 68     }
 69 
 70     /**
 71      * 初始化商品个数
 72      */
 73     public static void initprduct() {
 74         int prdnum = 100;// 商品个数
 75         string key = "prdnum_100001";
 76         string clientlist = "clientlist";// 抢购到商品的顾客列表
 77         jedis jedis = redisutil.getinstance().getjedis();
 78 
 79         if (jedis.exists(key)) {
 80             jedis.del(key);
 81         }
 82 
 83         if (jedis.exists(clientlist)) {
 84             jedis.del(clientlist);
 85         }
 86 
 87         jedis.set(key, string.valueof(prdnum));// 初始化
 88         redisutil.returnresource(jedis);
 89     }
 90 
 91 }
 92 
 93 /**
 94  * 顾客线程
 95  *
 96  * @author linbingwen
 97  *
 98  */
 99 class clientthread implements runnable {
100     jedis jedis = null;
101     string key = "prdnum_10001";// 商品主键
102     string clientlist = "clientlist";//// 抢购到商品的顾客列表主键
103     string clientname;
104 
105     public clientthread(int num) {
106         clientname = "编号=" + num;
107     }
108 
109     public void run() {
110         try {
111             thread.sleep((int)(math.random()*5000));// 随机睡眠一下
112         } catch (interruptedexception e1) {
113         }
114         while (true) {
115             system.out.println("顾客:" + clientname + "开始抢商品");
116             jedis = redisutil.getinstance().getjedis();
117             try {
118                 jedis.watch(key);
119                 int prdnum = integer.parseint(jedis.get(key));// 当前商品个数
120                 if (prdnum > 0) {
121                     transaction transaction = jedis.multi();
122                     transaction.set(key, string.valueof(prdnum - 1));
123                     list<object> result = transaction.exec();
124                     if (result == null || result.isempty()) {
125                         system.out.println("悲剧了,顾客:" + clientname + "没有抢到商品");// 可能是watch-key被外部修改,或者是数据操作被驳回
126                     } else {
127                         jedis.sadd(clientlist, clientname);// 抢到商品记录一下
128                         system.out.println("好高兴,顾客:" + clientname + "抢到商品");
129                         break;
130                     }
131                 } else {
132                     system.out.println("悲剧了,库存为0,顾客:" + clientname + "没有抢到商品");
133                     break;
134                 }
135             } catch (exception e) {
136                 e.printstacktrace();
137             } finally {
138                 jedis.unwatch();
139                 redisutil.returnresource(jedis);
140             }
141 
142         }
143     }
144 
145 }