如何防止秒杀抢购超卖?
程序员文章站
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 }
上一篇: 原来这就是网络连图。 影视笑话
下一篇: 了解姜茶的功能,让你爱上喝姜茶