基于设计模式,实现分布式锁的资源管理

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;
	}

	@Override
	public 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对象,并在此基础上添加了自动资源管理的功能,从某种角度来看,也体现了装饰器模式的思想。

相关推荐
渊渟岳2 小时前
掌握设计模式--装饰模式
设计模式
zh路西法4 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
夏旭泽5 小时前
设计模式-备忘录模式
设计模式·备忘录模式
蓝染-惣右介5 小时前
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
java·设计模式
weisian1516 小时前
Redis篇--常见问题篇7--缓存一致性2(分布式事务框架Seata)
redis·分布式·缓存
不能只会打代码7 小时前
Java并发编程框架之综合案例—— 分布式日志分析系统(七)
java·开发语言·分布式·java并发框架
Elastic 中国社区官方博客7 小时前
如何通过 Kafka 将数据导入 Elasticsearch
大数据·数据库·分布式·elasticsearch·搜索引擎·kafka·全文检索
马剑威(威哥爱编程)8 小时前
分布式Python计算服务MaxFrame使用心得
开发语言·分布式·python·阿里云
学计算机的睿智大学生8 小时前
Hadoop的生态系统所包含的组件
大数据·hadoop·分布式