Java实现比率限定器

应用背景:

游戏抽奖,控制抽奖命中的最大次数,当抽奖命中次数达到上限,再继续抽奖无法出现命中情况;控制抽奖命中最低次数,确保流逝次数范围内至少命中次数。

package com.yx.demo.rate;

/**
 * RateLimiter
 * 比率限定器,把比率限定在指定范围内。 <p/>
 * <p>
 * 比率限定器必须要制定perCount和maxLimit,即每perCount最多发生maxLimit,比如
 * 每10000次最多发生3次,minLimit可选,是发生的下限。<p/>
 * <p>
 * 比率限定器不包含随机方法,使用比率限定器需手动调用elapse(流逝)方法来增加
 * 当前的流逝次数,比如1000此的流逝到第500次。使用isUnderLimit方法获取是否仍然
 * 在比率限定中,如果在比率限定中,那么返回true,并且增加一次计数,大于等于
 * 最高限制时,isUnderLimit将返回false
 *
 * @author yx
 * @date 2019/12/20 23:40
 */
public class RateLimiter {
    /**
     * 每次数量,每次这个数量下限制多少次的成功数
     */
    private int perCount;

    /**
     * 最高限制
     */
    private int maxLimit;

    /**
     * 最低限制,默认0
     */
    private int minLimit = 0;

    /**
     * 当前累计经过数量,已经流逝的次数
     */
    private int currentCount = 0;

    /**
     * 当前累计赢得数量,已经成功的次数
     */
    private int currentWinCount = 0;

    /**
     * 当前限制量,可能会大于maxLimit
     */
    private int currentLimit = 0;

    /**
     * 默认构造函数。
     */
    public RateLimiter() {
    }

    /**
     * 带有构造函数的比率限定器。
     *
     * @param perCount 每次数量
     * @param maxLimit 最高数量
     * @param minLimit 最小数量
     */
    public RateLimiter(int perCount, int maxLimit, int minLimit) {
        this.perCount = perCount;
        this.maxLimit = maxLimit;
        this.minLimit = minLimit;
        this.currentLimit = this.maxLimit;
    }

    /**
     * 流逝一次次数。
     */
    public synchronized void elapse() {
        currentCount++;

        if (currentCount >= perCount) {
            // 把上次间隔的未达到最低概率的移到以后,让
            // 后来者有更高的机会,从而保证最低数
            int lastUnUsed = minLimit - currentWinCount;
            if (lastUnUsed < 0) {
                // 不能为负,否则将会减少以后的机会
                lastUnUsed = 0;
            }

            currentLimit = lastUnUsed + maxLimit;
            currentCount = 0;

            // 重置当前的赢的次数
            currentWinCount = 0;
        }
    }

    /**
     * 赢的一次。
     */
    public synchronized void win() {
        currentWinCount++;
        currentLimit--;
        assert (currentLimit >= 0);
    }

    /**
     * 是否当前还在指定的比率限定中,此方法不会增加流逝次数。
     *
     * @return 是否还在比率限定中
     */
    public synchronized boolean isUnderLimit() {
        if (currentWinCount < currentLimit) {
            return true;
        } else {
            return false;
        }
    }

    public int getPerCount() {
        return perCount;
    }

    public void setPerCount(int perCount) {
        this.perCount = perCount;
    }

    public int getMaxLimit() {
        return maxLimit;
    }

    public void setMaxLimit(int maxLimit) {
        this.maxLimit = maxLimit;
        if (this.currentLimit == 0) {
            this.currentLimit = this.maxLimit;
        }
    }

    public int getMinLimit() {
        return minLimit;
    }

    public void setMinLimit(int minLimit) {
        this.minLimit = minLimit;

        if (this.currentLimit == 0) {
            this.currentLimit = this.minLimit;
        }
    }

    public int getCurrentCount() {
        return currentCount;
    }

    public void setCurrentCount(int currentCount) {
        this.currentCount = currentCount;
    }

    public int getCurrentWinCount() {
        return currentWinCount;
    }

    public void setCurrentWinCount(int currentWinCount) {
        this.currentWinCount = currentWinCount;
    }

    public int getCurrentLimit() {
        return currentLimit;
    }
}
发布了142 篇原创文章 · 获赞 258 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/conconbenben/article/details/103640082