Java 代码不';除非包含println或断点,否则无法工作
作为大学计算机图形学课程的一部分,我正在制作一个基本的多人射击游戏 对于客户端->服务器通信,我使用UDP。每个客户端都有一个ClientController线程,该线程处理用户输入并通过套接字将其发送到服务器。服务器正在运行ServerClientManager,它处理消息,并在游戏状态下更新玩家的对象 以下是ClientController的代码:Java 代码不';除非包含println或断点,否则无法工作,java,multithreading,sockets,networking,udp,Java,Multithreading,Sockets,Networking,Udp,作为大学计算机图形学课程的一部分,我正在制作一个基本的多人射击游戏 对于客户端->服务器通信,我使用UDP。每个客户端都有一个ClientController线程,该线程处理用户输入并通过套接字将其发送到服务器。服务器正在运行ServerClientManager,它处理消息,并在游戏状态下更新玩家的对象 以下是ClientController的代码: /** * A class that handles communication from client to server. */ pu
/**
* A class that handles communication from client to server.
*/
public class ClientController implements Runnable {
private String serverAddress;
int serverPort;
Integer clientId;
@SuppressWarnings("unused")
private boolean forward, backward, left, right, fire, up, down;
public ClientController (String serverAddress, int serverPort) {
System.out.println("ClientController started");
this.serverAddress = serverAddress;
this.serverPort = serverPort;
clientId = null;
reset();
}
public synchronized void forward() {
forward = true;
}
...
private synchronized void reset() {
forward = false;
backward = false;
left = false;
right = false;
fire = false;
up = false;
down = false;
}
@Override
public void run() {
System.out.println("ClientController thread is running");
while (true) {
//System.out.println("tick");
if (clientId != null) {
try {
ClientUpdate update = new ClientUpdate(forward, backward, left, right, fire, up, down, clientId);
ClientUDPSender sender = new ClientUDPSender(serverAddress, 1233, update.toJson());
Thread worker = new Thread(sender);
worker.start();
Thread.sleep(15);
reset();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public synchronized void setClientId(int clientId) {
this.clientId = clientId;
}
}
这将向服务器发送更新。启动时,客户端启动此线程。然后,客户端通过另一个类中的TCP单独接收它的clientId(初始游戏状态和连接信息通过TCP发送)。设置clientId后,UDP客户端将开始通信
奇怪的是,除非我做两件事中的一件,否则这一切都不起作用:
1) 取消对System.out.println(“勾选”)行的注释
2) 在try语句中放置一个断点,然后从那里继续
如果我只是按原样运行程序,它永远不会到达try语句的内部。如果我包含println或断点,它运行得很好,更新会按预期传播到服务器
我很困惑
奇怪的是,除非我做两件事中的一件,否则这一切都不起作用:
1) 取消对System.out.println(“勾选”)行的注释
PrintStream.println(…)
是一种synchronized
方法,因此我怀疑您的问题在于内存同步
然后,客户机通过另一个类中的TCP单独接收其clientId
如果我理解的话,似乎另一个线程正在设置clientId
。如果这是真的,则必须将其标记为volatile
,否则旋转线程将看不到更新。即使setClient(…)
方法是synchronized
的,while(true)
循环中没有任何东西可以跨越内存障碍并更新旋转线程内存缓存中的clientId
值。将clientId
标记为volatile
后,可以删除setter上的synchronized
关键字
volatile Integer clientId;
而且,纺纱很恶心。可能会加入一个
线程。睡眠(10)
或是让它慢一点的东西?是的,就是这样!读取volatile变量,然后将clientId标记为volatile。现在可以了。谢谢