【发布时间】:2017-07-21 12:46:00
【问题描述】:
我需要重复发送 tcp 包到服务器。发送速度为每秒 800 条消息,每条消息要匀速发送,1.25 毫秒。我计算发送所用的时间,并将线程休眠 1.25 毫秒 - 使用 Thread.sleep() 发送时间。但是我发现 Thread.sleep() 在我的机器上至少需要 1ms,即使我将 1ns 传递给它。在网上搜索了一番后,我将睡眠方式改为忙等待:
long delayNanoSec = 1250000;
long endTime = System.nanoTime() + delayNanoSec;
while (System.nanoTime() < endTime);
这在delayNanoSec 12500000 时运行良好,它会在delayNanoSec 左右花费一些时间,但是当设置为1250000 时,它会比delayNanoSec 随机花费更长的时间。我将代码更改为记录 System.nanoTime() 在每个循环中使用的时间:
long[] timeUsed = new long[50000];
long delayNanoSec = 1250000;
long endTime = System.nanoTime() + delayNanoSec;
long lastTime = 0;
int index = 0;
do {
lastTime = System.nanoTime();
timeUsed[index++] = lastTime;
}while(lastTime < endTime);
for(int i = 0; i < times-1; i++) {
System.out.println("INDEX: " + i + " TIME USED: " + (nanos[i+1] - nanos[i]));
}
我得到了这样的东西:
INDEX: 1729 TIME USED: 226
INDEX: 1730 TIME USED: 387
INDEX: 1731 TIME USED: 240
INDEX: 1732 TIME USED: 240
INDEX: 1733 TIME USED: 219
INDEX: 1734 TIME USED: 246
INDEX: 1735 TIME USED: 289
INDEX: 1736 TIME USED: 283
INDEX: 1737 TIME USED: 245
INDEX: 1738 TIME USED: 244
INDEX: 1739 TIME USED: 4254974
在多次测试这段代码后,看起来 System.nanoTime() 会花费很长时间才能随机返回。在大多数情况下,它花费大约 250ns,但有时花费超过 3-4ms。
有谁知道这其中的原因吗?还是有更好的方法来完成这项工作? (控制每次发送之间的时间)
顺便说一句,对不起我的英语,希望你明白我的意思。
【问题讨论】:
-
你试过 ScheduledExecutorService 吗?
-
不要期望来自 JVM 的实时行为。 JVM 可能会随时暂停应用程序以执行 GC、去优化、偏向锁撤销、代码缓存清理或其他维护任务。
-
是否总是在循环的最后一次迭代中较长时间,当它因为超过
endTime而爆发时? -
@ChrisNauroth 它大部分时间都发生在最后一次调用中,并且花费超过 1 毫秒。并且在某个时候发生在中间,但通常花费不超过90000ns。当延迟小于 12500 或大于 12500000 时,它几乎不会发生。我尝试了 jdk 6 和 jdk 8,得到相同的结果。
-
@apangin 我写了一个测试类,只包括一个忙碌的等待来测试它。只有一个原始的 int 类型来存储时间,以及一个反复调用 nanoTime 方法的 while 循环。非常简单,没有我自己编写的对象创建代码,并且总是在延迟在我的问题中描述的范围内时发生。这感觉很奇怪。
标签: java performance