【问题标题】:Weird nested-if statement execution奇怪的嵌套 if 语句执行
【发布时间】:2022-01-30 21:18:25
【问题描述】:

我用 Java 编写的一些代码有一个有趣的问题。我正在使用 jdk-17.0.1 在最新版本的 eclipse 中执行此代码。代码的目的是每隔几毫秒对我​​的屏幕进行一次屏幕截图,但前提是运行是真的。一开始,跑步是假的。我可以通过按某个键将运行设置为真。这是代码

        double timePerTick = 1_000_000_000/fps;
        double delta = 0;
        long now;
        long lastTime = System.nanoTime();
        while (true) {
            now = System.nanoTime();
            delta+= (now-lastTime)/timePerTick;
            lastTime = now;
            if (delta >= 1) {
                //for some reason code only works if this print statement here
                //System.out.println("WOWEE");
                if (running) {
                    //Create rectangle screen-capture around cursor
                    BufferedImage image = robot.createScreenCapture(new Rectangle(0,0, width, height));
                    try {
                        output.write(("Capture taken \n").getBytes());
                        System.out.println("WRITTEN!");
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        System.out.println("BRUH!");
                        e1.printStackTrace();
                    }
                }
                delta--;
            }
        }       

问题是 if (running) 语句永远不会运行,即使 running 为真。但是,当我在 if(delta) 代码之后取消注释 System.out.println 语句时,它运行良好。像这样:

        double timePerTick = 1_000_000_000/fps;
        double delta = 0;
        long now;
        long lastTime = System.nanoTime();
        while (true) {
            now = System.nanoTime();
            delta+= (now-lastTime)/timePerTick;
            lastTime = now;
            if (delta >= 1) {
                //for some reason code only works if this print statement here
                System.out.println("WOWEE");
                if (running) {
                    //Create rectangle screen-capture around cursor
                    BufferedImage image = robot.createScreenCapture(new Rectangle(0,0, width, height));
                    try {
                        output.write(("Capture taken \n").getBytes());
                        System.out.println("WRITTEN!");
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        System.out.println("BRUH!");
                        e1.printStackTrace();
                    }
                }
                delta--;
            }
        }       

在第一个代码中,没有打印任何内容,但在第二个代码中,WOWEE 被一遍又一遍地打印。顺便说一句,如果运行开始时为真,那么两个代码都可以正常工作。但是,如果您从 running = false 切换到 running = true,第一个代码不会打印任何内容,但第二个代码会从不打印任何内容变为打印 WOWEE。这有什么原因吗?

顺便说一句,如果需要的话,输出是一个 FileOutputStream 实例。

【问题讨论】:

  • 顺便说一句,我不确定 print 语句是否是唯一发生这种情况的语句。我尝试使用 int x = 0,但这并没有改变任何东西。
  • 可以分享一下运行声明吗?
  • @tcgumus boolean running = false
  • @user16320675 我不知道 volatile 是什么意思,所以我不确定
  • @user16320675 谢谢,它有效。如果您将其发布为答案,我会接受它

标签: java eclipse debugging


【解决方案1】:

user16320675 在 cmets 中找到了我的问题的答案,但由于某种原因,他们删除了他们的 cmets。我等着看他们是否会回来,但他们没有。所以,我会发布他们给我的信息。我的程序不起作用的原因是因为变量“running”被多个线程访问,一个线程是主线程,另一个线程是监视键盘输入的线程。当多个线程访问一块内存时,您必须将其声明为“易失性”以确保不会发生同步问题。像这样

public static volatile boolean running;

更多信息在这里https://www.baeldung.com/java-volatile

【讨论】:

  • 是的。另一个不需要volatile 的选项是使用AtomicBoolean,这是一个线程安全的类,但volatile boolean 也可以。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-03
相关资源
最近更新 更多