我正在使用 KryoNet java 库以及 slick 开发基于服务器/客户端的游戏。当服务器类收到来自客户端的连接时,它会向客户端发送必要的启动信息,包括玩家编号。收到此消息后,客户端就会开始流畅并开始正常运行。其代码是:
boolean started = false;
while(!started){
System.out.println(cs.playerNum);
if(cs.playerNum != -1){
cs.startSlick();
started = true;
}
}
当从服务器接收到值时,playerNum 由另一个线程设置。有一段时间我无法让它工作(cs.startSlick()从未被调用),最终我感到沮丧并开始在每次循环运行时记录playerNum。通过添加 System.out.println(cs.playerNum),代码开始工作,循环将正确评估并启动 slick。
System.out.println 怎么可能做到这一点?我尝试用其他函数替换它,甚至其他以 cs.playerNum 作为参数的函数,但只有当我专门打印 cs.playerNum 时,我才能让循环工作。 如果我需要包含更多源代码,我可以,但问题似乎直接在这里,因为我尝试用其他函数替换 System.out.println 但没有成功。
最佳答案
当你说“playerNum是由另一个线程设置的”时,你有点回答了你自己的问题。你所拥有的是经典的竞赛条件。如果您的代码能够足够快地执行,那么在需要时,playerNum 将不会被设置。但是,如果某些事情延迟或“中断”您的代码,那么另一个线程将有时间设置playerNum 值,并且您的代码将按您的预期工作。
执行 IO 的系统调用会在线程等待 IO 操作发生时强制挂起线程。当您调用 System.out.println 时,就会发生这种情况,这会导致看似紧凑的代码短暂暂停,让出给另一个线程,然后允许您检索所需的值。
这是一个非常基本的线程问题,编写线程代码时您将遇到更复杂的线程问题。因此,我绝对建议您花一些时间阅读一般的线程技术,并了解同步函数以及 wait() 和 notification() 的工作原理,正如评论中所建议的那样。
关于Java System.out.println() 影响程序流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32870405/