Java是否对单线程应用程序强制执行串行

Java是否对单线程应用程序强制执行串行,java,optimization,jvm,single-threaded,Java,Optimization,Jvm,Single Threaded,我在一个线程上运行一些JUnit测试,它们以不确定的方式失败。我让一个人告诉我,优化JVM(OracleHotsp64位17.1-b03)执行指令的速度有问题。我很难相信java规范会允许这样做,但我找不到具体的参考 Wikipedia声明,单个线程必须像串行线程一样在线程内执行,所以我不必担心执行顺序与我编写的不同。 示例代码: @Test public void testPersistence() throws Exception { // Setup final long

我在一个线程上运行一些JUnit测试,它们以不确定的方式失败。我让一个人告诉我,优化JVM(OracleHotsp64位17.1-b03)执行指令的速度有问题。我很难相信java规范会允许这样做,但我找不到具体的参考

Wikipedia声明,单个线程必须像串行线程一样在线程内执行,所以我不必担心执行顺序与我编写的不同。

示例代码:

@Test
public void testPersistence() throws Exception
{
    // Setup
    final long preTestTimeStamp = System.currentTimeMillis();

    // Test
    persistenceMethod();

    // Validate
    final long postTestTimeStamp = System.currentTimeMillis();
    final long updateTimeStamp = -- load the timestamp from the database -- ;
    assertTrue("Updated time should be after the pretest time", updateTimeStamp >= preTestTimeStamp);
    assertTrue("Updated time should be before the posttest time", updateTimeStamp <= postTestTimeStamp);
}

void persistenceMethod()
{
    ...
    final long updateTime = System.currentTimeMillis();
    ...
    -- persist updateTime to the database --
    ...
}
@测试
public void testPersistence()引发异常
{
//设置
final long preTestTimeStamp=System.currentTimeMillis();
//试验
persistenceMethod();
//证实
最终长postTestTimeStamp=System.currentTimeMillis();
final long updateTimeStamp=--从数据库加载时间戳--;
assertTrue(“更新的时间应在预测试时间之后”,updateTimeStamp>=预测试时间戳);

assertTrue(“更新的时间应该在后测试时间之前”,updateTimeStamp应该很容易确定mySql(或您的持久性代码)是否正在做一些事情。让您的persistenceMethod()返回它持久化的值,并与您读取的值进行比较。它们肯定应该匹配

我想知道是否是currentTimeMillis()的可信度受到了质疑:

以毫秒为单位返回当前时间。请注意 返回值的时间为毫秒,即 值取决于基础操作系统,可能更大。 例如,许多操作系统以数十秒为单位测量时间 毫秒


考虑到您正在进行>=测试,我不太清楚这可能是如何体现的,但这让我想知道您到底得到了什么时间。

应该很容易确定mySql(或您的持久性代码)是否正在做什么。让您的persistenceMethod()返回它保留的值并与您读取的值进行比较。它们肯定应该匹配

我想知道是否是currentTimeMillis()的可信度受到了质疑:

以毫秒为单位返回当前时间。请注意 返回值的时间为毫秒,即 值取决于基础操作系统,可能更大。 例如,许多操作系统以数十秒为单位测量时间 毫秒


考虑到您正在进行>=测试,我不太清楚这可能是如何表现出来的,但这让我想知道您到底得到了什么时间。

这真的很奇怪。如果这些语句可能会产生副作用,影响后续语句,Java肯定不会重新排列语句并以不同的顺序执行它们

我认为发生此错误是因为
System.currentTimeMillis
没有您想象的那么精确。该方法的API文档说明:

以毫秒为单位返回当前时间。请注意,虽然返回值的时间单位为毫秒,但该值的粒度取决于基础操作系统,可能更大。例如,许多操作系统以几十毫秒为单位测量时间


这听起来很奇怪,但在某些情况下,时间甚至似乎在倒退,因此
currentTimeMillis
在某一时刻返回的值可能低于它在前一时刻返回的值。请参见以下问题:

,这真的很奇怪。如果se语句可能具有影响后续语句的副作用

我认为发生此错误是因为
System.currentTimeMillis
没有您想象的那么精确。该方法的API文档说明:

以毫秒为单位返回当前时间。请注意,虽然返回值的时间单位为毫秒,但该值的粒度取决于基础操作系统,可能更大。例如,许多操作系统以几十毫秒为单位测量时间


这听起来很奇怪,但在某些情况下,时间甚至似乎在倒退,因此
currentTimeMillis
在某一时刻返回的值可能会低于它在前一时刻返回的值。请看这个问题:

JVM执行语句的顺序不正确的可能性非常小,我认为您可以非常容易地忽略它如果JVM有这样一个bug,除了你的这个程序之外,它还会出现在很多地方

诚然,currentTimeMillis不能保证精确到毫秒,但时钟向后运行的可能性几乎与JVM执行语句的顺序不正确的可能性一样遥远

我已经写了很多很多程序来测试我感兴趣的一个函数需要多长时间来执行,方法是在函数启动前取currentTimeMillis,执行函数,完成后取currentTimeMillis,然后用减法计算经过的时间。我从来没有这样的程序给我一个负时间

我想到的一些可能性:

  • 在将时间戳保存到数据库或读回时,您的代码中出现错误。您没有显示该代码,因此我们无法知道是否存在错误

  • 舍入。我手边没有MySQL实例,所以我不确定时间戳的精度。如果它没有毫秒那么精确,那么这就很容易解释你的问题。例如,假设它只精确到秒。你得到的是pre-time=01:00:00.1,update-time=01:00:00.2,post-time=01:00:00.4。但是更新时间节省了一个小时s 01:00:00,因为这是精度的限制,所以当您读回它时,更新时间发布时间