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

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

相关推荐
四谎真好看1 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程1 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t2 小时前
ZIP工具类
java·zip
lang201509282 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan3 小时前
第10章 Maven
java·maven
百锦再3 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说3 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多4 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring
百锦再4 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
DokiDoki之父4 小时前
Spring—注解开发
java·后端·spring