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

    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;
    }

你可能感兴趣的:(分布式)