java中的时间同步

发布于 2024-08-03 14:37:43 字数 2755 浏览 6 评论 0原文

在 for 循环中,我通过检索和处理车辆信息来控制基于模拟步骤的交通模拟器 SUMO。为了确保我的程序“实时”模拟(1 个模拟步骤 = 1 秒),我想在处理阶段之后让我的程序休眠,直到下一个时间步骤开始。为了获得更好的结果,我根据最初采用的参考时间戳来计算时间戳。

循环如下所示:

    System.out.println("start of traffic simulation ...");

    for (int i = 0; i < stepCount; i++)
    {
        System.out.println("step: " + i);

        // set before timeStamp
        beforeTimeStamp = System.currentTimeMillis();

        if (firstStep)
        {
            // get reference timeStamp
            referenceTimeStamp = beforeTimeStamp;
            firstStep = false;
        }
        else
        {
            // get next vehicleVector
            vehicleVector = masterControl.traCIclient.simulateStep();
        }

        // process vehicleVector

        // set after timeStamp
        afterTimeStamp = System.currentTimeMillis();

        processingTime = afterTimeStamp - beforeTimeStamp;

        // calculate sleepTime
        sleepTime = referenceTimeStamp + ((i + 1) * 1000) - afterTimeStamp;

       // sleep for sleepTime ms
       Thread.sleep(sleepTime);
    }

    System.out.println("end of traffic simulation ..."); 

这是一些变量的输出:

step:   0                                                                                                         
beforeTimeStamp 1252317242565                                                                                   
reference time: 1252317242565                                                                                   
processing time: 394                                                                                            
test time: 1252317243565                                                                                        
afterTimeStamp 1252317242959                                                                                    
sleepTime: 606                                                                                                  
step: 1                                                                                                         
beforeTimeStamp 1252317242961                                                                                   
processing time: 665                                                                                            
test time: 1252317244565                                                                                        
afterTimeStamp 1252317243626                                                                                    
sleepTime: 939 (exspected: 1000 - 665 = 335)                                                                                                  

如您所见,睡眠时间仅对于第一个模拟步骤是正确的。我不知道我在这里会出什么问题。有人有想法吗?

BR,

马库斯

Inside a for-loop I'm controlling the simulation-step-based traffic simulator SUMO by retrieving and processing information of vehicles. To make sure that my program simulates in "real-time" (1 simulation-step = 1 second) I want to sleep my program after the processing phase until the next time step begins. To get better results I'm calculating the time stamp based on a initially taken reference time stamp.

The loop looks like this:

    System.out.println("start of traffic simulation ...");

    for (int i = 0; i < stepCount; i++)
    {
        System.out.println("step: " + i);

        // set before timeStamp
        beforeTimeStamp = System.currentTimeMillis();

        if (firstStep)
        {
            // get reference timeStamp
            referenceTimeStamp = beforeTimeStamp;
            firstStep = false;
        }
        else
        {
            // get next vehicleVector
            vehicleVector = masterControl.traCIclient.simulateStep();
        }

        // process vehicleVector

        // set after timeStamp
        afterTimeStamp = System.currentTimeMillis();

        processingTime = afterTimeStamp - beforeTimeStamp;

        // calculate sleepTime
        sleepTime = referenceTimeStamp + ((i + 1) * 1000) - afterTimeStamp;

       // sleep for sleepTime ms
       Thread.sleep(sleepTime);
    }

    System.out.println("end of traffic simulation ..."); 

Here's the output of some variables:

step:   0                                                                                                         
beforeTimeStamp 1252317242565                                                                                   
reference time: 1252317242565                                                                                   
processing time: 394                                                                                            
test time: 1252317243565                                                                                        
afterTimeStamp 1252317242959                                                                                    
sleepTime: 606                                                                                                  
step: 1                                                                                                         
beforeTimeStamp 1252317242961                                                                                   
processing time: 665                                                                                            
test time: 1252317244565                                                                                        
afterTimeStamp 1252317243626                                                                                    
sleepTime: 939 (exspected: 1000 - 665 = 335)                                                                                                  

As you can see the sleep time is only correct for the first simulation step. I have no clue what might me going wrong here. Does anybody has an idea?

BR,

Markus

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

骄兵必败 2024-08-10 14:37:43

使用标准 Java 无法休眠精确的时间,因为 Java 不提供有关线程调度的绝对保证。 Java 会受到操作系统分配 CPU 时间的影响,并且您的程序将受到垃圾收集暂停的影响,这是不可预测的。

如果您确实需要可预测的执行,那么您需要查看Java 实时规范这显然是多余的!

您可以使用 java.util.concurrent 包中的 ScheduledExecutorService 来定期执行任务(或者通过休眠一段时间) ,或以特定速率执行)。用法:

import static java.util.concurrent.*

Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS)

但这不准确(请参阅JavaDoc):

但请注意,由于网络时间同步协议、时钟漂移或其他因素,相对延迟的到期时间不必与任务启用的当前日期一致 >

(强调矿)

You cannot sleep for an exact amount of time using standard Java due to the fact that Java offers no absolute guarantees about thread-scheduling. Java is affected by when it is allotted CPU time by the OS and your program will be affected by garbage-collection pauses, which are unpredictable.

If you do need predictable execution then you need to look at the realtime-specification for Java. Which is clealy overkill here!

You can use ScheduledExecutorService in the java.util.concurrent package to execute tasks periodically (either by sleeping for a period, or executing at a particular rate). Usage:

import static java.util.concurrent.*

Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS)

But this is not exact (see the JavaDoc):

Beware however that expiration of a relative delay need not coincide with the current Date at which the task is enabled due to network time synchronization protocols, clock drift, or other factors

(Emphasis mine)

远山浅 2024-08-10 14:37:43

为什么不休眠 1000 -processingTime ?这将是您能得到的最接近正确答案的结果。

您的解决方案仅适用于第一步,因为它仅适用于第一步。您假设您将在 referenceTime + (step * 1000) 开始处理每个步骤,但您没有考虑开销(线程休眠、打印、垃圾收集)。
打印 referenceTimeStamp + ((i + 1) * 1000) - beforeTimeStamp 看看我的意思

Why not sleep for 1000 - processingTime ? It would be the closest you can get to a correct answer.

Your solution only works on the first step because it's only correct for the first step. You assume that you will start your processing for each step at referenceTime + (step * 1000), but you are not taking overhead (thread sleeping, prints, garbage collection) into account.
Print out referenceTimeStamp + ((i + 1) * 1000) - beforeTimeStamp to see what I mean

淡忘如思 2024-08-10 14:37:43

从 Java 5 开始,Java 中有一个简单的标准解决方案。

请查看 ScheduledExecutorService.

它看起来像这样:

        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(new MyCode(), 0, 1, TimeUnit.SECONDS);

其中 MyCode 类实现了 runnable 接口并且每秒执行一次。

这不是实时保证,但对于您的情况来说应该足够了。

There is a simple standard solution in Java starting with Java 5.

Take a look at ScheduledExecutorService.

It will look something like this:

        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(new MyCode(), 0, 1, TimeUnit.SECONDS);

Where MyCode class implements runnable interface and will be executed once a second.

This is not a real time guarantee but should be sufficient for your case.

墟烟 2024-08-10 14:37:43

正如 其他人所强调的,您应该休眠 1000 处理时间。

忽略 Java SE 不提供实时平台(因此您无法获得精确度)这一事实,我也许会看一下 Timer 类,特别是 Timer.scheduleAtFixedRate(),它将定期安排任务。

As highlighted by others, you should be sleeping for 1000 - processing time.

Ignoring the fact that Java SE doesn't provide a real-time platform (and as such you won't get precision), I would perhaps take a look at the Timer class, and particularly Timer.scheduleAtFixedRate(), which will look after scheduling tasks at regular intervals.

雾里花 2024-08-10 14:37:43

您确定输出来自同一个程序吗?请参阅内嵌突出显示的差异,

step:   0                                                                                                         
beforeTimeStamp 1252317242565                                                                                   
reference time: 1252317242565                                                                                   
processing time: 394                                                                                            
test time: 1252317243565                                                                                        
afterTimeStamp 1252317242959                                                                                    
sleepTime: 606 #### It didn't sleep this long at all
step: 1                                                                                                         
beforeTimeStamp 1252317242961 #### This is only 2ms from last afteTimeStamp                                                                                 
processing time: 665                                                                                            
test time: 1252317244565                                                                                        
afterTimeStamp 1252317243626                                                                                    
sleepTime: 939 (exspected: 1000 - 665 = 335)  #### This is to make up the deficit from last sleep                                                                                                

拳头睡眠中存在 604 (606-2) 缺陷。因此 939 (335 + 604) 是第二个循环的正确睡眠时间。

Java的sleep并不准确,但也不可能相差这么远。我认为要么您在调试器中中断程序,要么代码与输出不匹配。

Are you sure the output is from the same program? See the discrepancy highlighted inline,

step:   0                                                                                                         
beforeTimeStamp 1252317242565                                                                                   
reference time: 1252317242565                                                                                   
processing time: 394                                                                                            
test time: 1252317243565                                                                                        
afterTimeStamp 1252317242959                                                                                    
sleepTime: 606 #### It didn't sleep this long at all
step: 1                                                                                                         
beforeTimeStamp 1252317242961 #### This is only 2ms from last afteTimeStamp                                                                                 
processing time: 665                                                                                            
test time: 1252317244565                                                                                        
afterTimeStamp 1252317243626                                                                                    
sleepTime: 939 (exspected: 1000 - 665 = 335)  #### This is to make up the deficit from last sleep                                                                                                

There were 604 (606-2) deficit in fist sleep. So 939 (335 + 604) is the correct sleep time for second loop.

Java's sleep is not accurate but it can't be this far off. I think either you interrupt the program in a debugger or the code doesn't match the output.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文