-1

我想知道是否有其他人遇到过这个问题。我游戏中的这一部分代码依赖于 system.out.println 语句才能工作。没有它,它将无法正常运行

while(isladder){
 t = Map.tiles[(int) (Player.x + 15 + ScrollManager.xoffset) / 32][(int) ((Player.y ) + ScrollManager.yoffset) / 32];
 if(t.row == 3 && t.col == 5){
        ScrollManager.dy = -.5;
        System.out.println(t.row);
 }else{
    ScrollManager.nogravity = false;
 }
}

这是在有人按下向上键时开始的线程中。这是我正在制作的 2d minecraft 游戏的梯子。如果没有 system.out.println 代码,播放器将一直漂浮在空中。有了它,玩家将像往常一样停在梯子的顶部

(更新)我只是通过添加一个 Thread.sleep(1) 来解决这个问题,以便它运行更顺畅

4

1 回答 1

1

您受到线程内内存缓存的影响,这是一种优化技术,当 JIT 确定给定的内存块没有同步问题并且不需要与主内存同步时,它会使用该技术来加速您的程序。

相关问题:如何演示java多线程可见性问题?

本质上发生的是这样的:

1) JIT 加载类,并在while()循环中读取 2)isladder变量没有声明volatile,也没有通过任何synchronized方式检索,所以 JIT 认为:
“哦,这个变量基本上是本地的 - 我有线程缓存本地的值isladder,并且只使用它,所以它运行得更快。”

当您在循环中不包含任何倾向于触发上下文切换的操作时,例如 Thread.sleep()、System.out.println() I/O,缓存的值isladder永远不会被刷新。

虽然 Thread.sleep() 表面上解决了问题,但它并没有解决代码中的根本问题,即缺乏对游戏状态的同步访问。您发布的这个线程似乎只修改了滚动窗口,因此相当无害,但是当您使用线程控制动画对象、敌人等事物时,糟糕的多线程实践会导致自发的、看似随机的、不可预测的结果。

于 2013-04-16T23:40:46.100 回答