java - 定时 while 循环不终止

标签 java timer while-loop timertask

<分区>

运行这段代码,我希望它会增加测试变量 5 秒,然后结束。

import java.util.Timer;
import java.util.TimerTask;

public class Test {
    private static boolean running;

    public static void main( String[] args ) {
        long time = 5 * 1000;       // converts time to milliseconds
        long test = Long.MIN_VALUE;
        running = true;

        // Uses an anonymous class to set the running variable to false
        Timer timer = new Timer(); 
        timer.schedule( new TimerTask() { 
            @Override
            public void run() { running = false; }
        }, time );

        while( running ) {
            test++;
        }

        timer.cancel();
        System.out.println( test );
    }
}

但是,当我运行它时,程序并没有结束(我假设,我已经给了它合理的时间)。但是,如果我将 while 循环更改为

    while( running ) {
        System.out.println();
        test++;
    }

程序在预期的时间内完成(并打印出很多行)。我不明白。为什么会出现这种行为?

最佳答案

根据 Java Memory Model无法保证非 volatile 字段何时从另一个线程可见。在您的情况下,您的主要方法是 JIT 编译的,JIT 编译器合理地假设 current 线程不会在循环中修改 running 变量,那么我们不应该费心阅读它在每次迭代中将循环转换为无限循环。甚至还有 FindBugs warning关于这个案例。

当你添加一个System.out.println调用时,似乎JIT编译器不能内联它,所以不能确定这个方法没有修改running变量, 因此它关闭了字段读取优化。然而,这不应被视为问题解决方案:即使您在内部有 System.out.println,新版本的 Java 也可能会更智能并优化您的循环。

关于java - 定时 while 循环不终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30473750/

相关文章:

java - StringBuilder 与 Java 中 toString() 中的字符串连接

java - 线程 "main"java.lang.UnsatisfiedLinkError : Unable to load library 'libtesseract302' : The specified module could not be found 中的异常

iphone - 定时器动画的问题

php - if 语句或 while 循环在 php 中对我失败

java - while 循环中的 StringIndexOutOfBoundsException

csv - 如何在 JMeter 的 while 循环中使用 CSV 数据集配置?

Java Regular Expression 的 Pattern 应该编译为静态数据成员还是实例变量?

Java泛型覆盖方法

java - 线程会让我的游戏在每台计算机上一致运行吗

Javascript - 测量 FPS 并将其与事件同步