我正在尝试编写一个支持设置tps值的线程库。但是,我有一个问题,当tps是例如15时,滴答声持续的平均时间将是66667 ms。由于一个线程只能休眠整毫秒,因此我的解决方案是创建一个查找表,其中所有值的总和为1000毫秒。
因此,如果我想每秒钟有15个滴答声,我只会在0到14之间进行for循环,并在表中查找最大睡眠时间。我的问题是如何计算查找表中的值?
我的方法如下:
int tps = 15;
int[] sleepTime = new int[tps];
float tickTime = 1000.0f / tps;
float increment = 1.0f - (tickTime - (int) tickTime);
float overflow = 0;
int c = 0;
for (int n = 0; n < tps; n++) {
if (overflow >= 1) overflow = 0;
sleepTime[n] = (int) tickTime + (int) Math.ceil(overflow);
c += sleepTime[n];
overflow += increment;
}
System.out.println(Arrays.toString(sleepTime));
System.out.println("Complete sleep time: " + c);
这对于15之类的较小值来说效果很好,但是当我希望具有31 tps之类的较高值时,所有计算值的总和大于1000(31为1007)。
答案 0 :(得分:1)
您可以逐步从剩余的睡眠时间中减去整数除法的值:
int[] tps(int tps) {
int[] sleepTimes = new int[tps];
for (int i = 0, remainder = 1000; i < tps; i++) {
int sleepTime = remainder / (tps - i);
sleepTimes[i] = sleepTime;
remainder -= sleepTime;
}
return sleepTimes;
}
tps(3)
的示例评估:
要使下限和上限值均匀分布,可以执行以下操作:
int[] tps(int tps) {
int[] sleepTimes = new int[tps];
int low = 1000 / tps; // the floored value
Arrays.fill(sleepTimes, low);
int mod = 1000 % tps; // number of ceiled values to insert
if (mod > 0) {
int high = low + 1; // the ceiled value
float rate = tps / (float) mod; // the insertion rate
for (int i = 0; i < mod; i++) {
sleepTimes[Math.round(i * rate)] = high;
}
}
return sleepTimes;
}
tps(21)
:[ 48 , 47 , 48 , 48 , 47 , 48 , 48 , 47 , 48 , 47 , 48 , 48 , 47 , 48 , 47 , 48 < / strong>, 48 , 47 , 48 , 48 , 47 ] < / p>
答案 1 :(得分:0)
Thread.sleep(long millis, int nanos)
睡眠毫秒和纳秒。
因此,计算出确切的睡眠时间,然后开除一名工人(在另一个线程中)并重新入睡。这意味着工人的执行时间无关紧要。
为避免漂移错误,请根据开始时间和计数器进行睡眠计算。每次知道之后,线程都会少睡觉一些,以补偿处理自己的睡眠计时器所需的少量时间。