模仿看门狗写个简单的分布式锁demo

文章介绍了如何使用Java在Spring框架下通过Redis实现线程安全的锁功能,包括tryLock方法获取锁、scheduleExpirationRenewal进行续期操作以及unLock释放锁的过程。
摘要由CSDN通过智能技术生成
    public void tryLock() {
//        判断key是否存在,存在则返回 用户信息
//        不存在则生成key,将信息(用户名,用户id,线程名)放入
        TYuanGong pcCurrentUser = TisUtils.getPcCurrentUser();
        String name = Thread.currentThread().getName();
        //=================================================
        // redis redis.call('exists', KEYS[1]) 存在为1 不存在为0
        //=================================================

        String xingMing = String.valueOf(pcCurrentUser.getXingMing());
        List<Object> resList = (List) redisTemplate.execute(new DefaultRedisScript<List>(
                        "local result = {};" +
                                "if (redis.call('exists', KEYS[1]) == 0) " +
                                "then " +
                                "redis.call('hmset', KEYS[1], ARGV[1], ARGV[2], ARGV[3], ARGV[4], ARGV[5], ARGV[6]);" +
                                "redis.call('expire', KEYS[1], 30);" +
                                "result[1] = 1;" +
                                "else " +
                                "result[1] = redis.call('hget', KEYS[1],ARGV[1]);" +
                                "end;" +
                                "return result;"
                        , List.class), Arrays.asList(OrderPreArrangementService.LOCK_KEY),
                "userName", xingMing, "userId", pcCurrentUser.getGongHao(), "threadName", name);


        String res = String.valueOf(resList.get(0));

        if (!"1".equals(res)) {
            if (xingMing.equals(res)) {
                throw new RuntimeException("算力君正在快马加鞭cpu中,请耐心等待!");
            }
            throw new RuntimeException(String.format("算力被%s占用中,请稍后再试!", res));
        }
//        开启续期操作
        this.scheduleExpirationRenewal(name);
    }

    private static volatile ArrayList<String> threadNames = new ArrayList<>();

    private void scheduleExpirationRenewal(String threadName) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                Long res = 1l;
                if (threadNames.contains(threadName)) return;
                threadNames.add(threadName);
                // 判断value是当前线程才续期,否则返回0代表结束
                while (res == 1l) {
                    try {
                        Thread.currentThread().sleep(1000 * 10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    res = (Long) redisTemplate.execute(new DefaultRedisScript<Long>(
                            "if (redis.call('exists', KEYS[1]) == 1) " +
                                    "then " +
                                    "if (redis.call('hget', KEYS[1], ARGV[2]) == ARGV[1]) " +
                                    "then " +
                                    "redis.call('expire', KEYS[1], 30);" +
                                    "return 1;" +
                                    "else " +
                                    "return 0;" +
                                    "end;" +
                                    "else " +
                                    "return 0;" +
                                    "end;"
                            , Long.class), Arrays.asList(OrderPreArrangementService.LOCK_KEY), threadName, "threadName");
                }
                threadNames.remove(threadName);
            }
        }).start();
    }

    public void unLock() {

        redisTemplate.execute(new DefaultRedisScript(
                "if (redis.call('exists', KEYS[1]) == 1) " +
                        "then " +
                        "if (redis.call('hget', KEYS[1], ARGV[2]) == ARGV[1]) " +
                        "then " +
                        "redis.call('del', KEYS[1]);" +
                        "end;" +
                        "end;"
                , Boolean.class), Arrays.asList(OrderPreArrangementService.LOCK_KEY), Thread.currentThread().getName(), "threadName");
    }
    @GetMapping("/testThread2")
    public AjaxResult testThread2() {
            this.preArrangementService.tryLock();

        try {

            for (int i = 0; i < 10; i++) {
                System.out.println("主线程~~");
                Thread.currentThread().sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("主线程结束,进行解锁");
            this.preArrangementService.unLock();
        }
        return null;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值