【发布时间】:2021-12-19 04:56:34
【问题描述】:
我正在研究 swing 和 graphics2D,我遇到了一些问题,如何精确睡眠?
因为对于 144 或 240 fps 的显示器,ms 太长了。使用 4.1667ms Thread.sleep 将导致非常不稳定的结果和时间被缩放。问题是有什么方法可以在 1 毫秒内实现真正的睡眠吗?
我做了一些研究,发现类似Thread.Sleep for less than 1 millisecond
根据帖子,事件睡眠(1)不会准确睡眠1ms,因为我的测试有100次结果:
551900
1932500
994600
939200
1903000
935000
958700
944200
938700
950800
953600
1920600
932500
954000
961700
1927400
930900
1936800
1913000
926500
1976200
957800
952000
940600
961000
971700
994800
1889500
1989800
907600
966100
1983600
1914300
1943300
999900
1911200
1988600
932500
1836100
1955500
913500
970200
956400
1902200
970300
1985300
1926100
990900
1804000
947700
1881400
933500
1963600
963000
928300
1913600
1016900
1824700
951600
1959900
938400
1951400
1957300
1965600
969400
1933800
936700
980000
961900
929500
1910000
936700
940100
976100
1975600
952100
986000
1959900
919300
1973500
1998700
1852000
931400
967500
1954200
2005800
1897200
968700
1925500
1945700
1917600
1946300
933200
957100
966400
944900
916000
934300
1887200
934200
没有一个是接近的,至少会导致10ms,其中一些甚至超过20ms!
而且 20 毫秒对于 60FPS 的显示器来说也是不可接受的。因为16.67ms是帧率。
我正在寻找 Thread.sleep
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
我什至不敢相信 java 只是将纳秒视为毫秒,如果超过 0.5 毫秒,而其他诸如 TimeUnit.sleep 或 Object.wait 之类的东西只需调用 thread.sleep 或转换为内部毫秒。那么这是否意味着在 windows 或 linux 或任何非实时操作系统中,没有办法精确睡眠?游戏引擎是如何做到的?
【问题讨论】:
-
与其尝试针对特定的刷新率进行编程,不如让您的代码尽可能快地运行并传递帧。您应该关注的是确保底层游戏模型与时钟(而不是 fps)同步,请参阅此处了解更多信息:gamedev.stackexchange.com/a/43349 和其他阅读:gamedev.stackexchange.com/questions/1589/…
-
您的下一个问题将是系统时钟本身。它通常仅准确 +/- 15 毫秒。你不需要这么精确。
-
你的问题的答案是:你不能。睡眠是不精确的。正如您所指出的,这部分是因为 Linux 不是 RT 操作系统。但即使是这样,在图形应用程序中使用
sleep通常也是错误的方法。 -
改看swing Timer类(我觉得不是更精确,只是更合适)
-
@JFan - 你没抓住重点。请参阅我的评论。
标签: java