Java 仅当while true循环中存在System.out.println()时,线程才能正确运行

Java 仅当while true循环中存在System.out.println()时,线程才能正确运行,java,multithreading,Java,Multithreading,基本上,我正在制作一个更新玩家位置的游戏,它使用以下线程: @Override public void run() { while(true) { System.out.println(); updatePos(x, y); } } 这很好,但是如果我删除System.out.println(),它就会停止工作。我不知道这是为什么,全班如下: public class Player extends Block implements KeyLis

基本上,我正在制作一个更新玩家位置的游戏,它使用以下线程:

@Override
public void run() {
    while(true) {
        System.out.println();
        updatePos(x, y);
    }

}
这很好,但是如果我删除System.out.println(),它就会停止工作。我不知道这是为什么,全班如下:

public class Player extends Block implements KeyListener, Runnable {

int x;
int y;
int speed;

boolean upPressed; 
boolean downPressed;
boolean rightPressed;
boolean leftPressed;

static Sprite sprite = new Sprite("grass.png");

public Player(int x, int y, int speed) {
    super(x, y, sprite);
    this.x = x;
    this.y = y;
    this.speed = speed;
    Thread playerThread = new Thread(this, "Player Thread");
    playerThread.start();
}

@Override
public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_UP) {
        y -= speed;
    }

    if (e.getKeyCode() == KeyEvent.VK_DOWN)
        downPressed = true;

    if (e.getKeyCode() == KeyEvent.VK_RIGHT)
        rightPressed = true;

    if (e.getKeyCode() == KeyEvent.VK_LEFT)
        leftPressed = true;

}

@Override
public void keyReleased(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_UP)
        upPressed = false;

    if (e.getKeyCode() == KeyEvent.VK_DOWN)
        downPressed = false;

    if (e.getKeyCode() == KeyEvent.VK_RIGHT)
        rightPressed = false;

    if (e.getKeyCode() == KeyEvent.VK_LEFT)
        leftPressed = false;

}

@Override
public void keyTyped(KeyEvent e) {

}

@Override
public void run() {
    while(true) {
        System.out.println();
        updatePos(x, y);
    }

}}
最后一点:关于布尔上下压,我唯一关注的是:

if (e.getKeyCode() == KeyEvent.VK_UP) {
    y -= speed;
}
环状

while(true) {
    updatePos(x, y);
}
会完全占用CPU。使用
println
它开始表现得更好的原因可能是因为每次迭代I/O都会产生几百个周期

我建议您根据所需的帧速率添加一个小的睡眠方法:

while (true) {
    try {
        Thread.sleep(10); // for 100 FPS
    } catch (InterruptedException ignore) {
    }
    updatePos(x, y);
}

或者,更好的方法是采用事件驱动方法,例如。(这更像是Java惯用语。)

我不知道这是否能解决问题,但看起来你给JVM带来了一段艰难的时光。。。 尝试在每次updatePos(x,y)调用之前添加一个短睡眠(这是实现游戏线程的正确方法)


}}您没有将代码发布到
updatePos
。但至少,您需要使该方法,以及按下
(以及使用
x
和/或
y
的任何其他方法)
同步

或者,您可以将
x
y
都设置为volatile,但是
x
y
可能会不同步地更新


但是,如果没有任何内存同步,一个线程的更改就不能保证可以从另一个线程看到。

还有另一种方法。您可以使用java.util.Timer类,该类专用于执行计划任务。例如,如果您现在需要2个线程周期性地执行某种不同的操作,那么它非常有用。使用计时器,您只需使用一个线程即可节省工作和计算机资源。在某些情况下,yield()也可以这样做。 例如,见。
本链接的作者不建议使用
yield
但是。

到底是什么不正常工作?它跑吗?是否输入updatePos?您可以使用断点来发现…您接受了修复问题的答案。但是,您的代码未同步,并且无法在其他一些计算机上工作,因此您也应该修复同步问题。此外,从构造函数启动线程被认为是一种不好的做法。可能是+1的重复,这可能是因为
System.out.println()
非常昂贵,无意中“修复了”问题。@Kublai:可能更多,因为
System.out.println
是同步的。@Chris为了在GUI线程和正在运行的线程之间进行有效的同步,GUI线程中的某些东西有时必须锁定在System.out.println使用的同一个锁上(无论该锁是什么)。甚至
睡眠(0)
确实对我有用。我还不知道为什么。但是如果没有
sleep(x)
,线程中while循环之后的指令将永远不会在线程停止时被调用。使用
sleep(x)
(即使使用
sleep(0)
)循环后的指令在我停止线程时被调用。这很有趣。哦,我在上面的问题上找到了我自己的答案:@Deza如果你对线程和同步知之甚少,请给出更详细的解释:
keyPressed
是从Swing线程调用的,因此该线程中的值
y
(一个cpu核心上的缓存具有新的
y
值)。但是,运行
run
updatePos
的线程可能运行在另一个cpu核心上,而本地缓存不知道它应该更新
y
(除非同步代码)。
@Override
public void run() {
    while(true) {
    Try
    {
        Thread.sleep(50);
    }
    catch (Exception e){}

    updatePos(x, y);
    }