【锁】定时任务推送数据-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秒内没有释放锁,其他线程将无法获取到锁,可能会导致程序出现长时间的等待或阻塞。

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

相关推荐
你不是我我6 小时前
【Java 开发日记】HTTP3 性能更好,为什么内网微服务依然多用 HTTP2?HTTP2 内网优势是什么?
java·开发语言·微服务
雪碧聊技术6 小时前
大模型爆火!Java后端如何抓住Agent全栈开发的风口
java·大模型·agent·全栈开发
Filwaod7 小时前
互联网大厂Java面试实战:Spring Boot微服务架构与AI技术栈深度解析
spring boot·微服务·大厂面试·java面试·技术干货·ai技术栈·程序员求职
逻辑驱动的ken8 小时前
Java高频面试场景题25
java·开发语言·深度学习·面试·职场和发展
AI人工智能+电脑小能手9 小时前
【大白话说Java面试题】【Java基础篇】第32题:Java的异常处理机制是什么
java·开发语言·后端·面试
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ10 小时前
通过java后端代码来实现给word内容补充格式文本内容控件,以及 设置控件的标记和标题
java·c#·word
無限進步D11 小时前
Java 面向对象高级 接口
java·开发语言
逸Y 仙X11 小时前
文章二十七:ElasticSearch ES查询模板(Search Template)高效复用实战
java·大数据·数据库·elasticsearch·搜索引擎·全文检索
二哈赛车手11 小时前
新人笔记---Spring AI的Advisor以及其底层机制讲解(涉及源码),包含一些遇见的Spring AI的Advisor缺陷问题的解决方案
java·人工智能·spring boot·笔记·spring