org.redisson.api.RLock,是目前较为常见的分部署锁实现方式。我们的目的是实现自动管理锁的获取和释放。
但遗憾的是,RLock并不实现AutoCloseable接口,因此不能直接用在try-with-resources结构中。不过,我们可以通过创建一个包装类或者辅助方法,使得RLock的使用更加符合try-with-resources模式。这样做的好处是使得代码更加简洁,并且能够保证即使发生异常也能够正确释放资源。
1.实现代码
1.1包装类
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import java.util.concurrent.TimeUnit;
/*** @Description: RLock并不实现AutoCloseable接口,因此不能直接用在try-with-resources结构中。* 创建一个包装类,使得RLock的使用更加符合try-with-resources模式。这样做的好处是使得代码更加简洁,并且能够保证即使发生异常也能够正确释放资源**/
@Slf4j
public class AutoCloseableLock implements AutoCloseable{/*** 锁定请求*/private final String target;/*** 要获取的锁。*/private final RLock lock;/***锁状态*/private final boolean locked;/*** 获取锁的等待时长*/private static final int WAIT_TIME = 3;/*** 占用锁的最大时长*/private static final int LEASE_TIME = 10;public AutoCloseableLock(RLock lock, String target) throws InterruptedException {this.lock = lock;// 尝试获取锁,并立即返回结果。如果获取成功,设置锁的自动释放时间。this.locked = lock.tryLock(WAIT_TIME,LEASE_TIME, TimeUnit.SECONDS);this.target = target;}public boolean isLocked() {log.info("=====redisson分布式锁,【{}】上锁成功=====",this.target);return this.locked;}@Overridepublic void close() {if (this.locked && lock.isHeldByCurrentThread()) {log.info("=====redisson分布式锁,【{}】开锁成功=====",this.target);lock.unlock();}}
}
1.2参数枚举类
public enum LockEnum {login("LOGIN", "用户登录请求");/*** 锁前缀*/private final String prefix;/*** 锁请求*/private final String target;LockEnum(String prefix, String target) {this.prefix = prefix;this.target = target;}public String getPrefix() {return prefix;}public String getTarget() {return target;}
}
1.3 类的使用
try (AutoCloseableLock autoLock = new AutoCloseableLock(redissonClient.getLock(StrUtil.format("{}_{}", LockEnum.login.getPrefix(), username)),LockEnum.login.getTarget())) {if (autoLock.isLocked()) {// 成功获取锁,执行业务逻辑...} else {// 获取锁失败的处理逻辑...}
} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 重新设置中断状态// 处理中断异常...
}
2设计模式讲解
在这个示例中,AutoCloseableLock包装了一个Lock对象,并确保了在try-with-resources语句结束时自动释放锁,这既体现了资源管理器模式的优势,也借助装饰器模式的理念,为Lock对象增加了自动资源管理的功能。
2.1 资源管理器(Resource Management)模式
资源管理器设计模式的核心思想是确保对于需要手动管理的资源(如文件、数据库连接或锁等),在使用完毕后能够自动释放,以避免资源泄漏。在Java中,try-with-resources语句是这一模式的一个体现,它要求资源实现AutoCloseable或Closeable接口。当try块执行完毕时,无论是正常完成还是因为异常退出,都会自动调用close()方法来释放资源。
AutoCloseableLock类通过实现AutoCloseable接口,使得锁资源可以在try-with-resources语句中自动管理,从而简化了锁的获取和释放过程,减少了编码错误导致的资源泄漏风险。
2.2 装饰器(Decorator)模式
装饰器设计模式允许向一个对象添加新的功能,而不改变其结构。这是通过创建一个包含了原始对象的新对象来实现的,即“装饰”了原始对象。在AutoCloseableLock的上下文中,虽然它的主要目的不是为了添加新功能,但它通过包装Lock对象,并在此基础上添加了自动资源管理的功能,从某种角度来看,也体现了装饰器模式的思想。