import org.springframework.data.redis.core.RedisTemplate;
@Resource
private RedisTemplate redisTemplate;
@Resource
private RedisUtil redisUtil;
//生成编码
public String getExchangeTicketCode(){
String date = df.get().format(new Date());
//序列前需要填充0补足6位
String serial = date + this.getUniquecouponCode();
return serial;
};
//为了防止并发问题 这里利用ThreadLocal来保护DateFormat对象
//当然也可以将DateFormat作为方法getSerial的局部变量,每次取都new一个
private static final ThreadLocal df = new ThreadLocal() {
protected DateFormat initialValue() {
return new SimpleDateFormat(“yyyyMMddHH”);
}
};
//获取100001以后的数
public String getUniquecouponCode() {
log.info(“UserExchangeTicketInfoServiceImpl getUniquecouponCode begin”);
String lockValue = String.valueOf(System.currentTimeMillis() + 5000);
String str=“DH”;
Boolean flag;
Integer couponCode;
while (true) {
flag = redisUtil.getlock(str + “_temp”, lockValue);
if (!flag) {
log.info(“当前有进程在获取券编码”);
} else {
if (null != redisTemplate.opsForValue().get(str)) {
couponCode = ((Integer) redisTemplate.opsForValue().get(str) + 1);
redisTemplate.opsForValue().set(str, (Integer) redisTemplate.opsForValue().get(str) + 1);
} else {
redisTemplate.opsForValue().set(str, 100001);
couponCode = 100001;
}
break;
}
}
log.info(“优惠券编码code为” + couponCode);
BaseResultResponse baseResultResponse = BaseResultResponse.success(new ArrayList<>());
redisUtil.unlock(str + “_temp”, lockValue);
return couponCode.toString();
}
public class RedisUtil {
@Autowired
private RedisTemplate redisTemplate;
public boolean getlock(String key, String value) {
//如果key值不存在,则返回 true,且设置 value
if (redisTemplate.opsForValue().setIfAbsent(key, value)) {
return true;
}
//获取key的值,判断是是否超时
String curVal = (String) redisTemplate.opsForValue().get(key);
if (StringUtils.isNotEmpty(curVal) && Long.parseLong(curVal) < System.currentTimeMillis()) {
//获得之前的key值,同时设置当前的传入的value。这个地方可能几个线程同时过来,但是redis本身天然是单线程的,所以getAndSet方法还是会安全执行,
//首先执行的线程,此时curVal当然和oldVal值相等,因为就是同一个值,之后该线程set了自己的value,后面的线程就取不到锁了
String oldVal = (String) redisTemplate.opsForValue().getAndSet(key, value);
if(StringUtils.isNotEmpty(oldVal) && oldVal.equals(curVal)) {
return true;
}
}
return false;
}
/**
* 解锁
* @param key
* @param value
*/
public void unlock(String key, String value) {
try {
String curVal = (String) redisTemplate.opsForValue().get(key);
if (StringUtils.isNotEmpty(curVal) && curVal.equals(value)) {
redisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}