可以利用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 }
来源:oschina
链接:https://my.oschina.net/u/4404479/blog/3744131