Heisenbug:线程在没有sysout的情况下运行

时间:2013-01-19 19:07:46

标签: java multithreading

我在编写一个简单的游戏时遇到了奇怪的行为。基本上,我创建了一个带有无限循环的线程,每隔几秒就在我的游戏中触发一个事件。使用Sysout(runAnimation)一切正常。但是,一旦我将其移除,就会发生均匀的停止。

看来system.out calll正在影响程序的行为,有没有人知道为什么会发生这种情况

这是循环:

private void run(){
            long lastTime = -1;
            while(true){
                int timePerStep = (int) Math.ceil(ANIM_TIME/frequency);
                System.out.println(runAnimation);
                if(runAnimation && System.currentTimeMillis() - lastTime > timePerStep){
                    lastTime = System.currentTimeMillis();
                    controller.step();
                    try {
                        Thread.sleep(timePerStep);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
    }

它是在我班级建设期间开始的,如下所示:

animThread = new Thread(new Runnable() {
            @Override
            public void run() {
                GUIView.this.run();
            }
        });
animThread.start();

2 个答案:

答案 0 :(得分:4)

System.out.println()调用是synchronized(大多数PrintWriter方法调用都是)所以我怀疑你的代码内部没有同步。我想知道runAnimation字段。它可能是在另一个线程中设置的吗?也许它需要volatile?在一个线程中修改并在另一个线程中读取的任何字段都需要为synchronizedvolatile。阅读Java thread tutorial around synchronization可能有所帮助。

如果没有看到更多的代码,很难指出它,但我怀疑这个答案无论如何都会有所帮助。

最后, 这是一个非常糟糕的做法。如果runAnimation也是true,也许你应该在循环中睡一段时间。另一个想法是使用runAnimation或其他信令机制暂停你的线程,直到它需要做动画。

答案 1 :(得分:0)

如果您的字段不是易失性的,JIT可以假设它不会更改并将其放在寄存器中,甚至可以在代码中内联它。在这个紧密循环中放置系统调用可以

  • 阻止JIT以这种方式优化代码,因为它无法假设线程是否修改了字段。
  • 减慢循环,使其不会运行10,000次(这是JIT启动的时间点)

有关详情,请参阅我在Java Memory Model and optimisation.

主题上撰写的文章