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

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

相关推荐
骆晨学长14 分钟前
基于springboot的智慧社区微信小程序
java·数据库·spring boot·后端·微信小程序·小程序
AskHarries19 分钟前
利用反射实现动态代理
java·后端·reflect
@月落19 分钟前
alibaba获得店铺的所有商品 API接口
java·大数据·数据库·人工智能·学习
bjzhang7520 分钟前
SpringBoot开发——整合SpringDoc实现在线接口文档
spring boot·springdoc
liuyang-neu25 分钟前
力扣 42.接雨水
java·算法·leetcode
z千鑫28 分钟前
【人工智能】如何利用AI轻松将java,c++等代码转换为Python语言?程序员必读
java·c++·人工智能·gpt·agent·ai编程·ai工具
Flying_Fish_roe42 分钟前
Spring Boot-Session管理问题
java·spring boot·后端
赚钱给孩子买茅台喝44 分钟前
智能BI项目第四期
java·spring boot·spring cloud·aigc
hai405872 小时前
Spring Boot中的响应与分层解耦架构
spring boot·后端·架构
陈大爷(有低保)2 小时前
UDP Socket聊天室(Java)
java·网络协议·udp