Redis分布式锁

zhangkun4884 2015-07-23 12:03:21
package demo.redislock;

import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RedisOperator {
// 线程池
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
30, 50, 5, TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(200),
new ThreadPoolExecutor.CallerRunsPolicy());

static {
// 初始化设置库存
RedisUtil.setString("zk_stock", "2000");
}

/**
* 库存操作
*
* @param num
* @return
*/
public static int stockOperate(int num) {
int result = 0;
while (true) {
// 锁定成功
if (RedisUtil.setnxString("zk_stock_lock",
(System.currentTimeMillis() + 1000) + "") > 0) {
//RedisUtil.expire("zk_stock_lock",1);//FYI:防死锁如果设置默认失效时间是两步操作,你需要先set内容后再设置超时时间。两步操作,在分布式操作中有可能中断,如果你set后还没有来得及设置expire,那么设置进去的key将永远不会释放了
result = op(num);
// 释放锁
RedisUtil.delete("zk_stock_lock");
break;
} else {
// 如果锁没有释放掉则后面的线程会进入死循环
String lastestMilStr = RedisUtil.getString("zk_stock_lock");
if (lastestMilStr != null && !"".equals(lastestMilStr)) {
long lastestMil = Long.parseLong(lastestMilStr);
// 锁超时了
if (System.currentTimeMillis() > lastestMil
&& (lastestMil + "").equals(RedisUtil.getSetString(
"zk_stock_lock",
(System.currentTimeMillis() + 1000) + ""))) {
result = op(num);
// 释放锁
RedisUtil.delete("zk_stock_lock");
} else {
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
return result;
}

private static int op(int num) {
int result = 0;
if (num > 0) {// 操作库存(+)
long ret = RedisUtil.increase("zk_stock", num);
// 操作成功
if (ret > 0) {
result = 1;
}
} else {// 操作库存(-)
int curStock = Integer.parseInt(RedisUtil.getString("zk_stock"));
if (curStock >= -num) {
long ret = RedisUtil.decrease("zk_stock", -num);
// 操作成功
if (ret >= 0) {
result = 1;
}
} else {
// 库存不足
result = -1;
}
}
return result;
}

public static void main(String[] args) {
int max = 10000;
Random random = new Random();
int[] stocks = new int[max];
for (int i = 0; i < max; i++) {
int n = random.nextInt(10) + 1;
if (i % 2 != 0) {
n = -n;
}
stocks[i] = n;
}
int opNum = 0;
for (int i = 0; i < stocks.length; i++) {
opNum += stocks[i];
}
System.out.println("最终库存操作数为:" + opNum);
// 模拟并发
for (int i = 0; i < max; i++) {
final int num = stocks[i];
threadPoolExecutor.execute(new Runnable() {
@Override
public void run() {
System.out.println("result=" + stockOperate(num));
}
});
}
threadPoolExecutor.shutdown();
}
}
...全文
54 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

81,090

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧