美文网首页
简单疲劳度模型设计(JAVA实现)

简单疲劳度模型设计(JAVA实现)

作者: 灰气球 | 来源:发表于2023-08-12 19:40 被阅读0次

应用场景

疲劳度模型在很多场景下都是必不可少的,比如限制用户在一定时间内发送短信的次数、限制用户在一定时间内请求接口的次数等等。通过限制用户的操作次数,可以避免用户过度使用某个功能或接口,从而保护系统的稳定性和安全性。

设计与功能

这个疲劳度模型包含了两个维度的疲劳度配置:全平台维度和userId维度。全平台维度的疲劳度配置是所有用户共享的,而userId维度的疲劳度配置是每个用户单独拥有的。模型中的consume方法用于消耗一个疲劳度,每次调用会检查全平台维度和userId维度的疲劳度是否已经用完。如果还有剩余,则消耗一个疲劳度并返回true;否则返回false。模型中还包含了设置全平台维度和userId维度疲劳度配置的方法。

用法

使用这个疲劳度模型非常简单。首先,需要创建一个FatigueModel对象。可以使用默认的配置,也可以自定义配置。然后,在需要限制操作次数的地方调用consume方法,传入userId参数即可。如果consume方法返回true,则说明还有剩余的疲劳度,可以进行操作;如果返回false,则说明疲劳度已经用完,需要等待疲劳度周期结束后才能进行操作。

编码实现

用户维度疲劳度模型默认一天20次
全平台维度的疲劳度默认一天10000次

package com.eden.core.model;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 疲劳度模型
 *
 * @author Eden
 */
@Slf4j
@NoArgsConstructor
public class FatigueModel {

    /**
     * 全平台维度的疲劳度配置-默认一天10000次
     */
    private int globalLimit = 10000;
    /**
     * 全平台维度的疲劳度配置-疲劳度周期 默认一天
     */
    private long globalPeriod = 24 * 60 * 60 * 1000;

    /**
     * 全平台维度的疲劳度配置-当前疲劳度次数
     */
    private int currentGlobalLimit = globalLimit;
    /**
     * 全平台疲劳度周期的开始时间
     */
    private long globalStartTime = System.currentTimeMillis();

    /**
     * userId维度的疲劳配置
     */
    private final Map<String, Integer> userLimits = new HashMap<>();
    private final Map<String, Long> userStartTimes = new HashMap<>();

    /**
     * userId维度的疲劳配置-默认一天20次
     */
    private int userIdLimit = 20;

    /**
     * userId维度的疲劳配置-疲劳度周期为一天
     */
    private long userIdPeriod = 24 * 60 * 60 * 1000;

    public FatigueModel(int globalLimit, int userIdLimit) {
        this.globalLimit = globalLimit;
        this.currentGlobalLimit = globalLimit;
        this.userIdLimit = userIdLimit;
    }

    public FatigueModel(int globalLimit, long globalPeriod, int userIdLimit, long userIdPeriod) {
        this.globalLimit = globalLimit;
        this.currentGlobalLimit = globalLimit;
        this.globalPeriod = globalPeriod;
        this.userIdLimit = userIdLimit;
        this.userIdPeriod = userIdPeriod;
    }

    /**
     * 用户调用一次,消耗一个疲劳度
     */
    public synchronized boolean consume(String userId) {
        // 获取当前时间
        long now = System.currentTimeMillis();

        // 更新全平台维度的疲劳度周期
        if (now - globalStartTime >= globalPeriod) {
            // 重置全平台维度的疲劳度
            currentGlobalLimit = globalLimit;
            // 更新全平台疲劳度周期的开始时间
            globalStartTime = now;
        }

        // 判断全平台维度的疲劳度是否已经用完
        if (currentGlobalLimit <= 0) {
            log.info(String.format("consume,currentGlobalLimit <= 0,userId=%s,now=%s,currentGlobalLimit=%s,globalStartTime=%s",
                    userId, now, currentGlobalLimit, globalStartTime));
            return false;
        }

        // 判断userId维度的疲劳度是否已经用完
        int limit = fetchUserLimit(userId);
        if (limit <= 0) {
            return false;
        }

        // 更新全平台维度的疲劳度和userId维度的疲劳度
        currentGlobalLimit--;
        userLimits.put(userId, limit - 1);
        return true;
    }

    /**
     * 设置全平台维度的疲劳度配置
     */
    public synchronized void setGlobalLimit(int limit, long period) {
        globalLimit = limit;
        currentGlobalLimit = limit;
        globalPeriod = period;
        globalStartTime = System.currentTimeMillis();
    }

    /**
     * 设置userId维度的疲劳度配置
     */
    public synchronized void setUserLimit(String userId, int limit, long period) {
        userLimits.put(userId, limit);
        userStartTimes.put(userId, System.currentTimeMillis() - period);
    }

    /**
     * 充值userId维度的疲劳度
     */
    public synchronized void addUserLimit(String userId, int limit) {
        Integer userLimit = userLimits.getOrDefault(userId, this.userIdLimit);
        userLimits.put(userId, userLimit + limit);
    }

    /**
     * 获取用户当前剩余疲劳度
     */
    public int fetchUserLimit(String userId) {
        long now = System.currentTimeMillis();
        // 获取用户的疲劳度周期和周期内可用次数
        int limit = userLimits.getOrDefault(userId, userIdLimit);
        Long userStartTime = userStartTimes.get(userId);
        // 判断是否在疲劳度周期内,如果不在则重置周期内可用次数
        if (Objects.isNull(userStartTime) || (now - userStartTime >= userIdPeriod)) {
            userStartTimes.put(userId, now);
            limit = userIdLimit;
            userLimits.put(userId, limit);
        }
        log.info(String.format("fetchUserLimit,userId=%s,now=%s,limit=%s,userStartTime=%s",
                userId, now, limit, userStartTime));
        return limit;
    }

    /**
     * 校验用户疲劳度
     */
    public boolean checkUserLimit(String userId) {
        return fetchUserLimit(userId) > 0;
    }
}

相关文章

  • java基础-day54-SpringMVC

    SpringMVC 1.springmvc简介 SpringMVC 是一种基于 Java 实现 MVC 设计模型的...

  • 书单

    《揭秘Java虚拟机:JVM设计原理与实现》(10分)分析 hotspot jvm 的实现(c/c++层)内存模型...

  • JAVA基础23种设计模式----简单工厂模式--MonkeyK

    JAVA基础23种设计模式----简单工厂模式--MonkeyKing 简单工厂模式属于类的创建模型模式,又叫静态...

  • SpringMVC

    SpringMVC简介: SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级...

  • SpringBoot整合SpringMVC框架

    SpringMVC框架概述: SpringMVC 是一种基于 Java 实现 MVC 设计模型的请求驱动类型的轻量...

  • 1. SpringMVC入门

    1. SpringMVC概述 SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻...

  • Java中单例模式你用的哪一种?

    一起讨论java中的单例模式。单例模式是java设计模式中算是最简单的设计模式了。 * java实现单例模式的写法...

  • 系统设计与分析学习笔记4

    Asg Task2 E-R模型 简单叙说 数据库逻辑模型 与 领域模型 的异同 数据模型是系统设计,以及实现的一部...

  • Java基础之内存模型

    Java基础之内存模型 目录 Java内存模型简单介绍 JVM介绍 存储方式 并发原因 Java内存模型与系统内存...

  • 软件观念革命——交互设计精髓pdf

    1. 目标导向设计 交互设计不是凭空猜测。 2. 实现模型和心智模型 用户界面应该避免实现模型,而支持用户心智模型...

网友评论

      本文标题:简单疲劳度模型设计(JAVA实现)

      本文链接:https://www.haomeiwen.com/subject/sgnxmdtx.html