1

我在编写一个简单的游戏时遇到了奇怪的行为。基本上,我创建了一个无限循环的线程,每隔几秒钟在我的游戏中触发一个事件。使用 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();
4

2 回答 2

4

System.out.println()调用是synchronized(大多数方法调用是) ,PrintWriter所以我怀疑您的代码内部有一些东西没有同步。我想知道这个runAnimation领域。难道是它设置在另一个线程中?也许它需要volatile?在一个线程中修改并在另一个线程中读取的任何字段都需要是synchronizedor volatile。阅读有关同步的 Java 线程教程可能会有所帮助。

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

最后,你真的希望你的线程一直旋转runAnimationistrue吗?这是一个非常糟糕的做法。runAnimation也许你也应该在循环中睡一段时间false。另一个想法是使用一个CountDownLatch或其他信号机制来暂停你的线程,直到它需要做动画。

于 2013-01-19T19:10:22.990 回答
0

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

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

有关更多详细信息,这是我写的一篇关于Java 内存模型和优化的文章。

于 2013-01-20T09:26:35.260 回答