程序中的锁就是为了解决临界资源访问的同步性问题,而单机版的锁比如synchronized,Lock,ReentrantLock等是针对单个JVM实现的锁,而分布式锁是针对集群实现的锁。本文实现的是基于Redisson实现的分布式锁。
RedissonRedLock在创建锁的时候一定要注意避免死锁的问题,RedissonRedLock提供了三个参数,可以通过设置leaseTime有效时间避免死锁问题,l通过waitTime设置自旋时间。
lock.tryLock(waitTime, leaseTime, unit)
waitTime:等待时间,如果锁资源已经被占用会等待指定时间,超过改时间扔不能加锁,则立即返回失败。
leaseTime:锁的有效时间,加锁成功,超过该时间自动释放锁,。
unit:时间单位
关于基于Redis与Redisson分布式锁基本介绍,之前写过一篇有详细介绍,
Redis分布式锁详解:https://blog.csdn.net/m0_37583655/article/details/119966588
<dependency>
<groupId>com.google.guavagroupId>
<artifactId>guavaartifactId>
<version>30.1.1-jreversion>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.6.3version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>commons-langgroupId>
<artifactId>commons-langartifactId>
<version>2.6version>
<scope>compilescope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.72version>
dependency>
<dependency>
<groupId>org.redissongroupId>
<artifactId>redissonartifactId>
<version>3.7.3version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
application.properties
# 端口名称
server.port=8080
spring.application.name=autolog
# redisson
auto.redisson.address=redis://10.39.201.10:6379
auto.redisson.password=xyelbrp46j57JNtsuCfmvaHU
auto.redisson.clientName=
auto.redisson.thread=4
auto.redisson.codec=org.redisson.codec.JsonJacksonCodec
auto.redisson.connectionMinimumIdleSize=4
auto.redisson.idleConnectionTimeout=10000
auto.redisson.pingTimeout=1000
auto.redisson.connectTimeout=10000
auto.redisson.timeout=3000
auto.redisson.retryAttempts=1
auto.redisson.retryInterval=1500
auto.redisson.reconnectionTimeout=3000
auto.redisson.failedAttempts=2
auto.redisson.subscriptionsPerConnection=5
auto.redisson.subscriptionConnectionMinimumIdleSize=1
auto.redisson.subscriptionConnectionPoolSize=50
auto.redisson.connectionPoolSize=64
auto.redisson.database=0
auto.redisson.dnsMonitoring=false
auto.redisson.dnsMonitoringInterval=5000
RedissonConfig
package com.zrj.autolog.lock;
import java.util.ArrayList;
import java.util.List;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.redisson.config.TransportMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.ClassUtils;
import io.netty.channel.nio.NioEventLoopGroup;
/**
* 分布式锁配置类
*
* @author zrj
* @since 2021/12/9
**/
@ConfigurationProperties(prefix = "auto.redisson")
public class RedissonConfig {
private static Logger logger = LoggerFactory.getLogger(RedissonConfig.class);
//format: 127.0.0.1:7000,127.0.0.1:7001;
private String address;
//single node properties
private int connectionMinimumIdleSize = 10;
private int idleConnectionTimeout = 10000;
private int pingTimeout = 1000;
private int connectTimeout = 10000;
private int timeout = 3000;
private int retryAttempts = 3;
private int retryInterval = 1500;
private int reconnectionTimeout = 3000;
private int failedAttempts = 3;
//multi nodes, password split by comma(,)
private String password = null;
private int subscriptionsPerConnection = 5;
private String clientName = null;
private int subscriptionConnectionMinimumIdleSize = 1;
private int subscriptionConnectionPoolSize = 50;
private int connectionPoolSize = 64;
private int database = 0;
private boolean dnsMonitoring = false;
private int dnsMonitoringInterval = 5000;
//master slave properties
private ReadMode readMode = ReadMode.MASTER;
//cluster properties
private int scanInterval = 1000;
private RedisClusterType type = RedisClusterType.REPLICATE;
private int thread; //当前处理核数量 * 2
private String codec = "org.redisson.codec.JsonJacksonCodec";
public List<RedissonClient> redissons() throws Exception {
List<RedissonClient> clients = new ArrayList<>();
if (RedisClusterType.SINGLE.equals(type)) {
clients.add(Redisson.create(configSingleNode(address, password)));
} else if (RedisClusterType.MASTERSLAVE.equals(type)) {
//TODO 3.2 master slave not support dns configure
Config config = new Config();
config.useMasterSlaveServers().setMasterAddress(address)
.addSlaveAddress(address)
.setMasterConnectionMinimumIdleSize(connectionMinimumIdleSize)
.setMasterConnectionPoolSize(connectionPoolSize)
.setSlaveConnectionMinimumIdleSize(connectionMinimumIdleSize)
.setSlaveConnectionPoolSize(connectionPoolSize)
.setReadMode(readMode)
.setDatabase(database)
.setSubscriptionsPerConnection(subscriptionsPerConnection)
.setClientName(clientName)
.setFailedSlaveCheckInterval(failedAttempts)
.setRetryAttempts(retryAttempts)
.setRetryInterval(retryInterval)
.setFailedSlaveCheckInterval(reconnectionTimeout)
.setTimeout(timeout)
.setConnectTimeout(connectTimeout)
.setIdleConnectionTimeout(idleConnectionTimeout)
.setPingTimeout(pingTimeout)
.setPassword(password);
Codec codec = (Codec) ClassUtils.forName(getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
config.setCodec(codec);
config.setThreads(thread);
config.setEventLoopGroup(new NioEventLoopGroup());
config.setTransportMode(TransportMode.NIO);
clients.add(Redisson.create(config));
} else if (RedisClusterType.CLUSTER.equals(type)) {
Config config = new Config();
config.useClusterServers()
.addNodeAddress(address)
.setScanInterval(scanInterval)
.setSubscriptionsPerConnection(subscriptionsPerConnection)
.setClientName(clientName)
.setFailedSlaveCheckInterval(failedAttempts)
.setRetryAttempts(retryAttempts)
.setRetryInterval(retryInterval)
.setFailedSlaveCheckInterval(reconnectionTimeout)
.setTimeout(timeout)
.setConnectTimeout(connectTimeout)
.setIdleConnectionTimeout(idleConnectionTimeout)
.setPingTimeout(pingTimeout)
.setPassword(password);
Codec codec = (Codec) ClassUtils.forName(getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
config.setCodec(codec);
config.setThreads(thread);
config.setEventLoopGroup(new NioEventLoopGroup());
config.setTransportMode(TransportMode.NIO);
clients.add(Redisson.create(config));
} else if (RedisClusterType.REPLICATE.equals(type)) {
String[] nodes = address.split(",");
if (password != null) {
String[] passwords = password.split(",");
int index = 0;
for (String node : nodes) {
clients.add(Redisson.create(configSingleNode(node, passwords[index])));
index++;
}
} else {
for (String node : nodes) {
clients.add(Redisson.create(configSingleNode(node, null)));
}
}
} else if (RedisClusterType.SENTINEL.equals(type)) {
//TODO
}
return clients;
}
private Config configSingleNode(String address, String password) throws Exception {
Config config = new Config();
config.useSingleServer().setAddress(address)
.setConnectionMinimumIdleSize(connectionMinimumIdleSize)
.setConnectionPoolSize(connectionPoolSize)
.setDatabase(database)
//.setDnsMonitoring(dnsMonitoring)
.setDnsMonitoringInterval(dnsMonitoringInterval)
.setSubscriptionConnectionMinimumIdleSize(subscriptionConnectionMinimumIdleSize)
.setSubscriptionConnectionPoolSize(subscriptionConnectionPoolSize)
.setSubscriptionsPerConnection(subscriptionsPerConnection)
.setClientName(clientName)
//.setFailedAttempts(failedAttempts)
.setRetryAttempts(retryAttempts)
.setRetryInterval(retryInterval)
//.setReconnectionTimeout(reconnectionTimeout)
.setTimeout(timeout)
.setConnectTimeout(connectTimeout)
.setIdleConnectionTimeout(idleConnectionTimeout)
.setPingTimeout(pingTimeout)
.setPassword(password);
Codec codec = (Codec) ClassUtils.forName(getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
config.setCodec(codec);
config.setThreads(thread);
config.setEventLoopGroup(new NioEventLoopGroup());
config.setTransportMode(TransportMode.NIO);
logger.info("inti the redisson client with config: {}", config.toJSON());
return config;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getConnectionMinimumIdleSize() {
return connectionMinimumIdleSize;
}
public void setConnectionMinimumIdleSize(int connectionMinimumIdleSize) {
this.connectionMinimumIdleSize = connectionMinimumIdleSize;
}
public int getIdleConnectionTimeout() {
return idleConnectionTimeout;
}
public void setIdleConnectionTimeout(int idleConnectionTimeout) {
this.idleConnectionTimeout = idleConnectionTimeout;
}
public int getPingTimeout() {
return pingTimeout;
}
public void setPingTimeout(int pingTimeout) {
this.pingTimeout = pingTimeout;
}
public int getConnectTimeout() {
return connectTimeout;
}
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getRetryAttempts() {
return retryAttempts;
}
public void setRetryAttempts(int retryAttempts) {
this.retryAttempts = retryAttempts;
}
public int getRetryInterval() {
return retryInterval;
}
public void setRetryInterval(int retryInterval) {
this.retryInterval = retryInterval;
}
public int getReconnectionTimeout() {
return reconnectionTimeout;
}
public void setReconnectionTimeout(int reconnectionTimeout) {
this.reconnectionTimeout = reconnectionTimeout;
}
public int getFailedAttempts() {
return failedAttempts;
}
public void setFailedAttempts(int failedAttempts) {
this.failedAttempts = failedAttempts;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getSubscriptionsPerConnection() {
return subscriptionsPerConnection;
}
public void setSubscriptionsPerConnection(int subscriptionsPerConnection) {
this.subscriptionsPerConnection = subscriptionsPerConnection;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public int getSubscriptionConnectionMinimumIdleSize() {
return subscriptionConnectionMinimumIdleSize;
}
public void setSubscriptionConnectionMinimumIdleSize(int subscriptionConnectionMinimumIdleSize) {
this.subscriptionConnectionMinimumIdleSize = subscriptionConnectionMinimumIdleSize;
}
public int getSubscriptionConnectionPoolSize() {
return subscriptionConnectionPoolSize;
}
public void setSubscriptionConnectionPoolSize(int subscriptionConnectionPoolSize) {
this.subscriptionConnectionPoolSize = subscriptionConnectionPoolSize;
}
public int getConnectionPoolSize() {
return connectionPoolSize;
}
public void setConnectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
}
public int getDatabase() {
return database;
}
public void setDatabase(int database) {
this.database = database;
}
public boolean isDnsMonitoring() {
return dnsMonitoring;
}
public void setDnsMonitoring(boolean dnsMonitoring) {
this.dnsMonitoring = dnsMonitoring;
}
public int getDnsMonitoringInterval() {
return dnsMonitoringInterval;
}
public void setDnsMonitoringInterval(int dnsMonitoringInterval) {
this.dnsMonitoringInterval = dnsMonitoringInterval;
}
public int getThread() {
return thread;
}
public void setThread(int thread) {
this.thread = thread;
}
public String getCodec() {
return codec;
}
public void setCodec(String codec) {
this.codec = codec;
}
public RedisClusterType getType() {
return type;
}
public void setType(String type) {
this.type = RedisClusterType.valueOf(type.toUpperCase());
}
public ReadMode getReadMode() {
return readMode;
}
public void setReadMode(String readMode) {
this.readMode = ReadMode.valueOf(readMode.toUpperCase());
}
public int getScanInterval() {
return scanInterval;
}
public void setScanInterval(int scanInterval) {
this.scanInterval = scanInterval;
}
}
RedissonAutoConfigure
package com.zrj.autolog.lock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Redisson配置类
*
* @author zrj
* @since 2021/12/9
**/
@Configuration
@ConditionalOnClass(RedissonRedDisLock.class)
@EnableConfigurationProperties(RedissonConfig.class)
public class RedissonAutoConfigure {
@Autowired
private RedissonConfig config;
@Bean
@ConditionalOnMissingBean
RedissonRedDisLock starterRedissonClient() {
return new RedissonRedDisLock(config);
}
}
RedisClusterType
package com.zrj.autolog.lock;
/**
* redis集群类型
*
* @author zrj
* @since 2021/12/9
**/
public enum RedisClusterType {
/**
* redis集群类型
*/
SINGLE,
MASTERSLAVE,
SENTINEL,
CLUSTER,
REPLICATE;
}
LockFailException
package com.zrj.autolog.lock;
/**
* 分布式锁异常
*
* @author zrj
* @since 2021/12/9
**/
public class LockFailException extends Exception {
private static final long serialVersionUID = -3816322588329303318L;
private String message;
public LockFailException(String message) {
super(message);
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
DistributeLock
package com.zrj.autolog.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
/**
* The distribute lock interface, support the lock, unlock action.
*
* @author zrj
* @since 2021/12/9
*/
public interface DistributeLock {
/**
* try lock on lock key until the lock is available, and won't release the lock until call unlock()
*
* @param lockKey lock name
* @return the lock object, use to unlock.
*/
Lock lock(String lockKey) throws LockFailException;
/**
* try lock on lock key wait for timeout seconds, and won't release the lock until call unlock()
*
* @param lockKey lock name
* @param timeout lock time out, unit is second
* @return the lock object, use to unlock.
*/
Lock lock(String lockKey, long timeout) throws LockFailException;
/**
* try lock on lock key wait for timeout unit, and won't release the lock until call unlock()
*
* @param lockKey lock name
* @param unit lock time out unit
* @param timeout lock time out, -1 means no time out
* @return
*/
Lock lock(String lockKey, TimeUnit unit, long timeout) throws LockFailException;
/**
* try lock on lock key wait for timeout unit, and won't release the lock until call unlock()
*
* @param lockKey lock name
* @param unit lock time out unit
* @param timeout lock time out, -1 means no time out
* @param leaseTime lock lease time, -1 means no lease time out
* @return
*/
Lock lock(String lockKey, TimeUnit unit, long timeout, long leaseTime) throws LockFailException;
/**
* try lock on lock key wait for timeout unit, if can't lock return false; if lock success return true and will
* lease the lock after lease time.
*
* @param lockKey
* @param unit
* @param waitTime
* @param leaseTime
* @return
*/
boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) throws LockFailException;
/**
* unlock the lock by the lock name.
*
* @param lockKey lock name
*/
void unlock(String lockKey);
/**
* unlock the lock
*
* @param lock lock
*/
void unlock(Lock lock);
}
RedissonRedDisLock
package com.zrj.autolog.lock;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import static java.util.stream.Collectors.toList;
/**
* The distribute lock interface, support the lock, unlock action.
*
* @author zrj
* @since 2021/12/9
**/
public class RedissonRedDisLock implements DistributeLock {
private static Logger logger = LoggerFactory.getLogger(RedissonRedDisLock.class);
private RedissonConfig config;
private List<org.redisson.api.RedissonClient> redissionClientList;
public RedissonRedDisLock(RedissonConfig config) {
this.config = config;
}
@PostConstruct
public void init() throws Exception {
this.redissionClientList = config.redissons();
}
@PreDestroy
public void destroy() {
redissionClientList.stream().forEach(client -> {
try {
client.shutdown();
} catch (Exception e) {
logger.warn(e.getMessage(), e);
}
});
}
@Override
public Lock lock(String lockKey) throws LockFailException {
return lock(lockKey, null, -1, -1);
}
@Override
public Lock lock(String lockKey, long waitTime) throws LockFailException {
return lock(lockKey, TimeUnit.SECONDS, waitTime);
}
@Override
public Lock lock(String lockKey, TimeUnit unit, long waitTime) throws LockFailException {
return lock(lockKey, unit, waitTime, -1);
}
/**
* 加锁
*
* @param lockKey redisLock Key值
* @param unit 时间单位
* @param waitTime 等待时间,如果锁资源已经被占用会等待指定时间,超过改时间扔不能加锁,则立即返回失败
* @param leaseTime 锁的有效时间,加锁成功,超过该时间自动释放锁
* @return java.util.concurrent.locks.Lock
*/
@Override
public Lock lock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) throws LockFailException {
logger.info("【{}】lock use redlock with name {} start...", Thread.currentThread().getName(), lockKey);
final String lockKeyFinal = lockKey;
//获取锁队列
List<RLock> rlocks = redissionClientList.stream().map(client -> client.getLock(lockKeyFinal)).collect(toList());
//初始化锁对象
RedissonRedLock lock = new RedissonRedLock(rlocks.toArray(new RLock[rlocks.size()]));
try {
if (lock.tryLock(waitTime, leaseTime, unit)) {
logger.info("【{}】lock use redlock with name {} end...", Thread.currentThread().getName(), lockKey);
return lock;
} else {
logger.error("lock use redlock with name {} failed.", lockKey);
throw new LockFailException("lock use redlock with name " + lockKey + " failed.");
}
} catch (InterruptedException e) {
logger.error("lock time expired");
throw new LockFailException("lock use redlock with name " + lockKey + " failed for " + e.getMessage());
}
}
@Override
public boolean tryLock(String lockKey, TimeUnit unit, long waitTime, long leaseTime) {
throw new UnsupportedOperationException("Red lock not support the try lock method.");
}
@Override
public void unlock(String lockKey) {
throw new UnsupportedOperationException("Red lock not support the unlock by name method, please use unlock(Lock lock)");
}
@Override
public void unlock(Lock lock) {
logger.info("【{}】unlock the redlock {} start...", Thread.currentThread().getName(), lock);
if (lock != null) {
lock.unlock();
logger.info("【{}】unlock the redlock {} end...", Thread.currentThread().getName(), lock);
} else {
logger.info("【{}】lock is null, {} don't need to unlock", Thread.currentThread().getName(), lock);
}
}
}
RedissonRedDisLockService
package com.zrj.autolog.lock;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
/**
* 分布式锁接口
*
* @author zrj
* @since 2021/12/9
**/
@Slf4j
@Service
public class RedissonRedDisLockService {
@Resource
private RedissonRedDisLock redDisLock;
/**
* 分布式锁测试
*/
public void redissonRedDisLockTest() {
//定义锁
Lock lock = null;
//获取lockKey
//String lockKey = getDateRandom();
String lockKey = "newRedDisLock1";
log.info("【{}】lock key name {}", Thread.currentThread().getName(), lockKey);
try {
//尝试加锁,加不上锁,则等待30秒,仍然加不上则直接返回失败。
//30秒以内加上锁,上锁以后180秒自动解锁,防止死锁发生,业务处理不超过3分钟(这个需要根据实际业务场景评估)
lock = redDisLock.lock(lockKey, TimeUnit.SECONDS, 10, 180);
if (lock == null) {
log.error("lock use redlock with name {} failed.", lockKey);
throw new RuntimeException("lock failed with name " + lockKey);
}
//执行业务逻辑
Thread.sleep(1000);
log.info("【{}】业务逻辑处理!", Thread.currentThread().getName());
} catch (Exception e) {
log.error("lock failed because {},{}", e.getMessage(), e);
throw new RuntimeException("lock failed with name " + lockKey);
} finally {
redDisLock.unlock(lock);
}
}
/**
* 加锁测试
*/
public void lockRedDisLock() throws LockFailException {
//永久锁,加不上锁,立即返回失败
//Lock permanentLock = redDisLock.lock("RedDisLock");
//永久锁,加不上锁,等待10秒,返回加锁失败
//Lock awaitLock = redDisLock.lock("RedDisLock", TimeUnit.SECONDS, 10, -1);
//临时锁,加不上锁,waitTime=-1的时候一直等待,会导致死锁,加上锁以后20秒自动解锁
//临时锁,加不上锁,waitTime=10的时候,超过10秒自动返回失败,加上锁以后20秒自动解锁
//Lock leaseLock = redDisLock.lock("RedDisLock", TimeUnit.SECONDS, 10, 20);
Lock newLeaseLock = redDisLock.lock("newRedDisLock1", TimeUnit.SECONDS, 10, 20);
log.info("RedDisLock加锁成功:{}", newLeaseLock);
}
/**
* 解锁测试
*/
public void unlockRedDisLock() throws LockFailException {
Lock lock = redDisLock.lock("RedDisLock");
redDisLock.unlock(lock);
log.info("RedDisLock解锁成功:{}", lock);
}
/**
* 生成日期字符串,例如:20211213095419569
*/
public String getDateRandom() {
return DateUtil.format(DateUtil.date(), "yyyyMMddHHmmssSSS");
}
/**
* 生成的是不带-的字符串,例如:b17f24ff026d40949c85a24f4f375d42
*/
public String getSimpleUUID() {
return IdUtil.simpleUUID();
}
}
DistributeLockController
package com.zrj.autolog.controller;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.zrj.autolog.entity.Response;
import com.zrj.autolog.lock.LockFailException;
import com.zrj.autolog.lock.RedissonRedDisLockService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.concurrent.*;
/**
* 分布式锁控制类
*
* @author zrj
* @since 2021-06-21 16:44:24
*/
@Slf4j
@RestController
@RequestMapping("/lock")
@Api(tags = "lock", description = "分布式锁")
public class DistributeLockController {
@Resource
private RedissonRedDisLockService redissonRedDisLockService;
// 自定义线程名称
private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("lock-thread-%d").build();
// 定义线程池
private static ExecutorService executor = new ThreadPoolExecutor(30, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
/**
* 测试接口
* 自定义过滤器,拦截器
*/
@GetMapping("/test")
@ApiOperation(value = "测试接口")
public Response<String> test() {
return Response.success("测试接口成功", null);
}
/**
* 分布式锁测试
*/
@GetMapping("/redissonRedDisLockTest")
@ApiOperation(value = "分布式锁测试")
public Response redissonRedDisLockTest() {
//启动10个线程验证分布式锁
for (int i = 0; i < 5; i++) {
executor.execute(() -> redissonRedDisLockService.redissonRedDisLockTest());
}
return Response.success("分布式锁测试成功", null);
}
/**
* 加锁测试
*/
@GetMapping("/lockRedDisLock")
@ApiOperation(value = "加锁测试")
public Response lockRedDisLock() {
try {
redissonRedDisLockService.lockRedDisLock();
} catch (LockFailException e) {
e.printStackTrace();
}
return Response.success("加锁测试", null);
}
/**
* 解锁测试
*/
@GetMapping("/unlockRedDisLock")
@ApiOperation(value = "解锁测试")
public Response unlockRedDisLock() {
try {
redissonRedDisLockService.unlockRedDisLock();
} catch (LockFailException e) {
e.printStackTrace();
}
return Response.success("解锁测试", null);
}
}