com.github.azbh111.utils.java.lang.Speedometer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils-java Show documentation
Show all versions of utils-java Show documentation
com.github.azbh111:utils-java
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;
}
}