使用的是springboot -data-redis
这个service
@Service
public class SecKillServiceImpl implements SekillService {
private static final int TIMEOUT =10* 1000;
@Autowired
private RedisLock redisLock;
static Map<String,Integer> products;
static Map<String,String> orders;
static Map<String,Integer> stock;
static
{
products=new HashMap<>();
orders=new HashMap<>();
stock=new HashMap<>();
products.put("123456",100000);
stock.put("123456",100000);
}
private String queryMap(String productId){
return "国庆 活动,皮蛋粥特价,限量粉"+products.get(productId)
+"还剩: "+stock.get(productId) + " 份"
+ "该商品成功下单的数目: "
+orders.size() +" 人";
}
@Override
public String querySeckillProductInfo(String productId) {
return this.queryMap(productId);
}
@Override
public void orderProductMockDiffUser(String productId) {
//加锁
long time=System.currentTimeMillis()+TIMEOUT;
if (! redisLock.lock(productId, String.valueOf(time))){
throw new SellException(101,"人也太多了,换个姿势试试") ;
}
int stockNum=stock.get(productId);
if (stockNum==0){
throw new SellException(100,"活动结束");
}else{
orders.put(KeyUtil.genUniqueKey(),productId);
stockNum=stockNum-1;
try{
Thread.sleep(100);
} catch ( InterruptedException e){
e.printStackTrace();
}
stock.put(productId,stockNum);
}
//解锁
redisLock.unlock(productId,String.valueOf(time));
}
这个是锁
@Component
public class RedisLock {
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
*加锁
* @param key productid作为key
* @param value 当前时间+超时时间
* @return
*/
public boolean lock(String key,String value){
if(stringRedisTemplate.opsForValue().setIfAbsent(key,value)){
return true;
}
//判断锁是否超时
String currentValue = stringRedisTemplate.opsForValue().get(key);
//如果锁过期
if (!StringUtils.isEmpty(currentValue)&&Long.parseLong(currentValue)<System.currentTimeMillis()){
// 获取上一个锁的时间
String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtils.isEmpty(oldValue)&&oldValue.equals(currentValue)){
return true;
}
}
return false;
}
/***
* 解锁
* @param key
* @param value
*/
public void unlock(String key,String value){
try {
String currentValue = stringRedisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue)&¤tValue.equals(value)){
stringRedisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
e.printStackTrace();
}
}