All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.azbh111.utils.java.lang.Speedometer Maven / Gradle / Ivy

The newest version!
package com.github.azbh111.utils.java.lang;

import java.util.Arrays;

/**
 * 速度计
 * 统计从new出来到的总里程
 * 并记录最近一段时间,每秒钟的总里程
 *
 * @author: zyp
 * @since: 2022/2/6 下午2:36
 */
public class Speedometer {
    private long[] data;
    private int capacity;
    private int second; // 经过了多少秒了
    private final long startTime = System.currentTimeMillis();

    public Speedometer() {
        this(4096); // 默认记录4096秒
    }

    public Speedometer(int size) {
        if (size <= 0) {
            capacity = 1;
        } else {
            capacity = ceilPowerOf2(size);
        }
        data = new long[capacity];
    }

    public void add(long count) {
        int head = head();
        set(head, get(head) + count);
    }

    /**
     * 返回最近second秒内的速度
     *
     * @param second second
     * @return double
     * @author zhengyongpan
     * @since 2022/2/6 下午3:20
     */
    public double speed(int second) {
        if (second <= 0) {
            throw new IllegalArgumentException();
        }
        int head = head();
        if (second > head) {
            second = head;
        }
        if (second >= capacity) {
            second = capacity - 1;
        }
        long from = get(head - second);
        long to = get(head - 1);
        return ((double) to - from) / second;
    }

    /**
     * 获取总的平均速度
     *
     * @param
     * @return double
     * @author zhengyongpan
     * @since 2022/2/6 下午3:28
     */
    public double speed() {
        int time = (int) ((System.currentTimeMillis() - startTime) / 1000);
        return ((double) get(second)) / time;
    }

    // 计算头在哪
    private int head() {
        int to = (int) ((System.currentTimeMillis() - startTime) / 1000);
        int from = this.second;
        if (to - from > this.capacity) {
            Arrays.fill(data, get(from));
        } else {
            long v = get(from);
            while (++from <= to) {
                set(from, v);
            }
        }
        this.second = to;
        return to;
    }


    private long get(int index) {
        return data[index & (capacity - 1)];
    }

    private void set(int index, long v) {
        data[index & (capacity - 1)] = v;
    }

    /**
     * 计算最高位1的索引, 从0开始
     *
     * @param v v
     * @return int
     * @author zhengyongpan
     * @since 2022/2/6 下午2:42
     */
    private static int indexOfHighestBit(int v) {
        if (v == 0) {
            return -1;
        }
        if (v < 0) {
            return 31;
        }
        int from = 0;
        int to = 31;
        while (from < to) {
            int mid = from + ((to + 1 - from) >> 1);
            if ((v >>> mid) > 0) {
//                高位有1
                from = mid;
            } else {
//                高位无1
                to = mid - 1;
            }
        }
        return from;
    }


    private static boolean isPowerOf2(int n) {
        if (n <= 0) {
            return false;
        }
        return (n & (n - 1)) == 0;
    }

    private static int ceilPowerOf2(int target) {
        if (target <= 0) {
            throw new IllegalArgumentException(String.format("非法输入: %s", target));
        }
        if (isPowerOf2(target)) {
            return target;
        }
        int highestBit = indexOfHighestBit(target);
        if (highestBit == 31) {
            return Integer.MAX_VALUE;
        }
        return (1 << highestBit) << 1;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy