添加分布式锁
/**
* 添加分布式锁
*
* @param key:key
* @param value:value用于解锁
* @return boolen
*/
private boolean getLock(String key, String value) {
Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent(key, value, 60, TimeUnit.SECONDS);
if (ObjectUtil.isNotNull(lock) && lock) {
log.info("成功获取到锁!");
return true;
}
return false;
}
/**
* 释放锁
*
* @param key :
* @param value :
*/
private void unlock(String key, String value) {
String s = stringRedisTemplate.opsForValue().get(key);
if (value.equals(s)) {
Boolean flage = stringRedisTemplate.opsForValue().getOperations().delete(key);
if (ObjectUtil.isNotNull(flage) && flage) {
log.info("释放锁成功!");
return;
}
}
log.info("释放锁失败!");
}
/**
* 使用分布式锁操作ArrayList
* @param list:模拟数据
*/
private void demo(List<Integer> list) {
String key = "lockDemo";
if (!CollectionUtils.isEmpty(list)) {
//创建线程池
ExecutorService executor = Executors.newFixedThreadPool(30);
//创建ArrayList ArrayList是线程不安全的,此处用于测试分布式锁是否生效
ArrayList<Integer> list1 = new ArrayList<>(list.size());
for (Integer integer : list) {
executor.submit(() -> {
String value = IdWorker.getIdStr();
try {
boolean lock = getLock(key, value);
if (lock) {
log.info("value= {},成功获取到锁, 执行超长业务!", value);
//模拟业务 对ArrayList进行操作
list1.add(integer);
} else {
long start = System.currentTimeMillis();
while (true) {
try {
log.info("value= {} , 进入等待获取锁........!", value);
Thread.sleep(100);
boolean lock1 = getLock(key, value);
if (lock1) {
log.info("value= {},等待后超长时间后,成功获取到锁,执行超长业务!", value);
//模拟业务 对ArrayList进行操作
list1.add(integer);
break;
}
long end = System.currentTimeMillis();
//参考具体业务,此处可以省略
if (end - start > 3 * 60 * 1000){
log.info("获取锁超时,舍弃任务!");
break;
}
} catch (InterruptedException e) {
log.error("获取锁发生异常:" + e.getMessage());
e.printStackTrace();
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
unlock(key, value);
}
});
}
//关闭线程池
executor.shutdown();
try {
executor.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("redis lock ArrayList.size= {}",list1.size());
}
}
模拟数据
@GetMapping("/redisDemo")
public void redisDemo() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(i);
}
demo(list);
}
返回结果:
备注:经测试 结合redis使用分布式锁 成功,该锁还不完善,有待继续调整