简体   繁体   English

Java如何在1ms下精准休眠

[英]How Java precise sleep under 1ms

I'm working on swing & graphic2D, And I ran into some issue, How to precise sleep?我正在研究 swing 和 graphic2D,我遇到了一些问题,如何精确睡眠?

Because for 144 or 240 fps monitor, ms is too long.因为对于 144 或 240 fps 的显示器来说,ms 太长了。 With 4.1667ms Thread.sleep will cause very unstable result and time been scaled.使用 4.1667ms Thread.sleep 将导致非常不稳定的结果并且时间被缩放。 Question is is there some way to real sleep under 1ms?问题是有什么方法可以在 1 毫秒内实现真正的睡眠吗?

I did some research and found something like this Thread.Sleep for less than 1 millisecond我做了一些研究,发现类似Thread.Sleep 的时间不到 1 毫秒

And according to the post, Event sleep(1) will not sleep accurate 1ms, As my test there is 100 times result:根据帖子,Event sleep(1) will not sleep accurate 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

None of them is close, At least will cause 10ms, And some of them even more then 20ms!它们都不是很接近,至少会导致 10ms,有些甚至超过 20ms!

And 20ms is unacceptable for even 60FPS monitor.即使是 60FPS 显示器,20ms 也是不可接受的。 Because 16.67ms is the frame rate.因为16.67ms是帧率。

And I seek into Thread.sleep我寻求进入 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);
}

I can't even believe java just treat nano second as ms if longer then 0.5ms, And other things like TimeUnit.sleep or Object.wait just call thread.sleep or convert into ms internal.我什至不敢相信 java 只是将纳秒视为毫秒,如果超过 0.5 毫秒,而其他诸如 TimeUnit.sleep 或 Object.wait 的东西只是调用 thread.sleep 或转换为毫秒内部。 So is that mean in windows or linux or any non-realtimeOS, There is no way to precise sleep?那么这是否意味着在 windows 或 linux 或任何非实时操作系统中,没有办法精确睡眠? How game engine do that?游戏引擎如何做到这一点?

You need not sleep yourselvies.你不需要自己睡觉。 You should run your code as fast as possible.你应该尽可能快地运行你的代码。 The monitor will help you synchronize your video output and you don't have to keep your code waiting for the monitor.监视器将帮助您同步视频输出,您不必让代码等待监视器。

Game engines relies on Delta time for making games frame rate independent, Delata time is nothing but elapsed time between the last frame and current frame.游戏引擎依赖 Delta 时间来使游戏帧率独立,Delata 时间只不过是最后一帧和当前帧之间经过的时间。 You can measure delta time as您可以将增量时间测量为

DeltaTime = 1/FPS

So you can use this variable to make the game independent by multiplying this with your game variables, for example if you want to move a player independent of Frame rate you would do something like因此,您可以使用此变量通过将其与您的游戏变量相乘来使游戏独立,例如,如果您想独立于帧速率移动玩家,您可以执行类似的操作

Player.position = Player.position + MovementSpeed * DeltaTime

If initial position = 10 , MovementSpeed = 1 If FPS = 60 , DeltaTime = 0.016666667 then distance after 1 second is如果初始position = 10 , MovementSpeed = 1如果FPS = 60 , DeltaTime = 0.016666667那么 1 秒后的距离是

Player.position = 10 + 1 * (0.016666667*60) which is '11' (Here it's multiplied with 60 to simply acomodate the fact that same calculation will run for 60 times when game is running at 60 FPS so Player.position will be updated by 0.016666666 for 60 Times) Player.position = 10 + 1 * (0.016666667*60)即“11”(这里乘以 60 只是为了适应这样一个事实:当游戏以 60 FPS 运行时,相同的计算将运行 60 次,因此 Player.position 将是由 0.016666666 更新 60 次)

If FPS = 30 , DeltaTime = 0.03333 then distance moved after 1 seconds is Player.position = 10 + 1*(0.03333*30) which is '11' So game can run independent of Frame Rates如果FPS = 30DeltaTime = 0.03333则 1 秒后移动的距离为Player.position = 10 + 1*(0.03333*30)即 '11' 所以游戏可以独立于帧速率运行

You could try to calculate DeltaTime like:您可以尝试计算 DeltaTime,如:

//In main Game loop
current time = getSystemTime()
Delta time = current time - old time 
old time = current time // save old time for next loop

Thread.sleep has 2 methods, one of which accepts nanoseconds. Thread.sleep有两种方法,其中一种接受纳秒。

 Thread.sleep(long millis, int nanos)

So Thread.sleep(1);所以Thread.sleep(1); is equal to Thread.sleep(0,1000000);等于Thread.sleep(0,1000000);

So if you want to sleep half of a milisecond, use所以如果你想睡半毫秒,使用

Thread.sleep(0,500000)

Helpful Links:-有用的网址:-

Add a decimal millisecond delay to Java code 向 Java 代码添加十进制毫秒延迟

Can a Thread sleep for less than half milli seconds in Java/ Other language? 线程可以在 Java/其他语言中睡眠少于半毫秒吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM