【锁】定时任务推送数据-redission加锁实例优化

文章目录

redission 加锁代码-有问题

java 复制代码
    /**
     * 收货入库物料标签(包装码)推送接口
     *
     * @throws Exception
     */
    public void synReceiveMaterialTags() throws Exception {
        String tag = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        String key = RedisKeyPre.synReceiveMaterialTagsLock;
        RLock rLock = redissonClient.getLock(key);
        try {
            // 尝试加锁,最多等待3秒,上锁以后1200秒自动解锁,没有Watch Dog,1200s后自动释放
            boolean res = rLock.tryLock(3, 1200, TimeUnit.SECONDS);
            if (!res) {
                Log.info(LogBuilder.builder().business("synReceiveMaterialTags:" + tag + ":获取锁失败,稍后重试").build());
                return;
            } else {
                wmsSyncService.synReceiveMaterialTags();
            }
        } catch (Exception e) {
            Log.error(LogBuilder.builder().business("synReceiveMaterialTags error:" + e).build());
        } finally {
            releaseLock(rLock);
        }
    }

    private void releaseLock(RLock rLock) {
        if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {
            rLock.unlock();
        }
    }

rLock.tryLock(3, 1200, TimeUnit.SECONDS)表示尝试获取锁,最多等待3秒,锁的持有时间为1200秒(20分钟),超过持有时间后锁会自动释放。这样可以避免锁被长时间占用,提高代码的健壮性和性能。

如果不需要等待时间和自动释放时间,可以将tryLock()方法的参数调整为rLock.tryLock(),这样会立即尝试获取锁,如果锁不可用,则立即返回结果。但是需要注意,这样可能会导致线程频繁尝试获取锁,增加系统负载和竞争,需要根据具体情况进行评估和调整。

优化代码

这段代码存在一些问题:

  1. 异常处理不够详细:在synReceiveMaterialTags方法中,捕获了异常并记录了错误日志,但没有对异常进行具体的处理。建议根据实际情况,对异常进行适当的处理,例如回滚事务、发送通知等。

  2. 锁的释放方式不正确:在releaseLock方法中,使用isLocked和isHeldByCurrentThread方法来判断锁是否被当前线程持有,并进行解锁操作。然而,这种方式可能存在并发问题,因为在判断锁状态和解锁之间,其他线程可能已经获取了锁并修改了锁状态。建议使用try-finally语句来确保锁的正确释放,无论是否发生异常。

  3. 日志记录不规范:在日志记录中,使用了字符串拼接的方式来构建日志信息。建议使用日志框架,如Log4j或Slf4j,来记录日志,并使用占位符或参数化日志的方式,以提高性能和可读性。

优化后的代码示例:

java 复制代码
public void synReceiveMaterialTags() {
	String tag = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
	String key = RedisKeyPre.synReceiveMaterialTagsLock;
	RLock rLock = redissonClient.getLock(key);
	try {
		// 尝试加锁,最多等待3秒,上锁以后1200秒自动解锁,没有Watch Dog,1200s后自动释放
		boolean res = rLock.tryLock(3, 1200, TimeUnit.SECONDS);
		if (!res) {
			Log.info("synReceiveMaterialTags:{}:获取锁失败,稍后重试", tag);
		return;
		} else {
		wmsSyncService.synReceiveMaterialTags();
		}
	} catch (Exception e) {
	Log.error("synReceiveMaterialTags error:{}", e);
	// 异常处理逻辑
	} finally {
		try {
		rLock.unlock();
		} catch (IllegalStateException e) {}
		// 锁已经

看门狗是什么?

在这段代码中,"没有Watch Dog"是指在加锁的过程中没有使用监视器(watchdog)来监控锁的状态。通常情况下,当一个线程获取了锁但在一定时间内没有释放锁时,监视器会检测到这种情况并自动释放锁,以防止死锁的发生。

在这段代码中,锁的超时时间设置为1200秒,但没有使用监视器来监控锁的状态。这意味着如果某个线程获取了锁后,在1200秒内没有释放锁,其他线程将无法获取到锁,可能会导致程序出现长时间的等待或阻塞。

为了避免这种情况,建议在加锁时使用监视器来监控锁的状态,并在一定时间内自动释放锁,以提高程序的健壮性和性能。

相关推荐
悟空聊架构15 分钟前
我的网站被攻击了,被干掉了 120G 流量,还在持续攻击中...
java·前端·架构
Dajiaonew1 小时前
Spring AI RAG 检索增强 应用
java·人工智能·spring·ai·langchain
IT古董4 小时前
第四章:大模型(LLM)】06.langchain原理-(3)LangChain Prompt 用法
java·人工智能·python
轻抚酸~7 小时前
小迪23年-32~40——java简单回顾
java·web安全
Sirius Wu9 小时前
Maven环境如何正确配置
java·maven
健康平安的活着10 小时前
java之 junit4单元测试Mockito的使用
java·开发语言·单元测试
Java小白程序员11 小时前
Spring Framework :IoC 容器的原理与实践
java·后端·spring
xuTao66711 小时前
Easy Rules 规则引擎详解
java·easy rules
m0_4805026412 小时前
Rust 入门 KV存储HashMap (十七)
java·开发语言·rust
杨DaB12 小时前
【SpringBoot】Swagger 接口工具
java·spring boot·后端·restful·swagger