我在单个线程上运行一些 JUnit 测试,它们以不确定的方式失败。有人告诉我,优化的 JVM(Oracle Hotspot 64 位 17.1-b03)正在执行指令以提高速度。我很难相信 java 规范会允许这样做,但我找不到具体的参考。
Wikipedia 声明单个线程必须强制执行线程内如同串行,因此我不必担心执行顺序与我所写的不同。 http://en.wikipedia.org/wiki/Java_Memory_Model#The_memory_model
示例代码:
@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 --
...
}
运行此测试代码时,它具有完全不确定的行为,有时它通过,有时如果在第一个断言上失败,有时它在第二个断言上失败。这些值总是在一两毫秒之内,所以并不是说持久性完全失败了。添加一个 Thread.sleep(2); 在每个语句之间确实减少了测试失败的次数,但并没有完全消除失败。
这可能是 JVM 的错误,还是数据库(MsSql)更有可能对存储的数据进行某种舍入?