有问题,以下代码无效 代码:
服务器
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
static ServerSocket serverSocket;
static Socket socket;
static DataOutputStream out;
static DataInputStream in;
static Users[] user = new Users[10];
public static void main(String[] args) {
try {
System.out.println("Server Started...");
serverSocket = new ServerSocket(7778);
System.out.println("Server Start.");
while (true) {
socket = serverSocket.accept();
for (int i = 0; i < 10; i++) {
if (user[i] == null) {
System.out.println("Conection from"
+ socket.getInetAddress());
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
user[i] = new Users(out, in, user, i);
Thread thread = new Thread(user[i]);
thread.start();
break;
}
}
}
} catch (IOException e) {
}
}
}
class Users implements Runnable {
DataOutputStream out;
DataInputStream in;
Users[] user = new Users[10];
String name;
int playerid;
int playeridln;
int xin;
int yin;
public Users(DataOutputStream out, DataInputStream in, Users[] user, int pid) {
this.out = out;
this.in = in;
this.user = user;
this.playerid = pid;
}
public void run() {
try {
out.writeInt(playerid);
} catch (IOException e1) {
System.out.println("Failed to send PlayerID");
}
while (true) {
try {
playeridln = in.readInt();
xin = in.readInt();
yin = in.readInt();
for (int i = 0; i < 10; i++) {
if (user[i] != null) {
user[i].out.writeInt(playeridln);
user[i].out.writeInt(xin);
user[i].out.writeInt(yin);
}
}
} catch (IOException e) {
user[playerid] = null;
break;
}
}
}
}
客户端
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Client extends JPanel implements Runnable, KeyListener {
private static final long serialVersionUID = 1L;
static Socket socket;
static DataInputStream in;
static DataOutputStream out;
int playerid;
int[] x = new int[10];
int[] y = new int[10];
boolean left, up, right, down;
int playerx;
int playery;
public Client() {
init();
}
public void init() {
try {
System.out.println("Conecting to serever...");
socket = new Socket("localhost", 7778);
System.out.println("Connection successful");
in = new DataInputStream(socket.getInputStream());
playerid = in.readInt();
out = new DataOutputStream(socket.getOutputStream());
Input input = new Input(in, this);
Thread thread = new Thread(input);
thread.start();
Thread thread2 = new Thread(this);
thread2.start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void updateCoordinates(int pid, int x2, int y2) {
this.x[pid] = x2;
this.y[pid] = y2;
}
public void paint(Graphics g) {
repaint();
for (int i = 0; i < 10; i++) {
g.drawOval(x[i], y[i], 5, 5);
}
}
public void run() {
while (true) {
if (right) {
playerx += 10;
}
if (left) {
playerx -= 10;
}
if (down) {
playery += 10;
}
if (up) {
playery -= 10;
}
if (right || left || up || down) {
try {
out.writeInt(playerid);
out.writeInt(playerx);
out.writeInt(playery);
} catch (Exception e) {
System.out.println("Erro Coordinates");
}
}
repaint();
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 37) {
left = true;
}
if (e.getKeyCode() == 38) {
up = true;
}
if (e.getKeyCode() == 39) {
right = true;
}
if (e.getKeyCode() == 40) {
down = true;
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 37) {
left = false;
}
if (e.getKeyCode() == 38) {
up = false;
}
if (e.getKeyCode() == 39) {
right = false;
}
if (e.getKeyCode() == 40) {
down = false;
}
}
public void keyTyped(KeyEvent e) {
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(300, 300);
f.getContentPane().add(new Client());
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class Input implements Runnable {
DataInputStream in;
Client client;
public Input(DataInputStream in, Client c) {
this.in = in;
this.client = c;
}
public void run() {
while (true) {
try {
int playerd = in.readInt();
int x = in.readInt();
int y = in.readInt();
client.updateCoordinates(playerd, x, y);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
当我运行代码时(运行多个窗口进行检查)它不起作用,即使圆圈应该移动..
请帮助解决它)
提前谢谢!
答案 0 :(得分:0)
这是相当复杂的东西。我可以看到两个问题。
小问题(我认为):Swing类和方法,只有极少数例外(例如Component / JComponent中的repaint()方法)必须在事件队列上运行。在您的客户端中,在启动线程上运行的main()方法创建一个JFrame并调用多个方法。每个人都这样做,我认为每个人都可以逃脱它,但这很危险。使用EventQueue.InvokeLater将代码放到UI线程上。我检查了你的run()方法,但它们似乎没有触及Swing,(除了对repaint()的合法调用),但要密切关注它们。从那里调用Swing方法,你会遇到更大的问题。
主要问题:在一些按钮代码(在UI线程上运行)中,客户端运行方法和中引用了一堆字段。 (playerx
,playery
,left
,right
,up
,down
)同步在这里确实不是问题。但是,JVM没有义务(尽管它可以,如果它想要)通知线程其他线程所做的更改。自己做了这个,我发现有时线程会立即看到变化,有时候会出现明显的延迟(导致恼人的,跳跃的图形),有时甚至永远不会。
语言规范要求在线程启动时,线程启动时,线程在连接完成时,线程进入同步块后,另一个线程在同一个对象上同步一个块后,当一个写入和读取volatile 字段,并在调用Atomic方法之后。
因此,您要做的是手动完成客户端类中的所有字段,并确保每个字段都标记为final
,volatile
,或仅在synchronized
块或中引用,仅在一个线程上引用(如Swing方法)。你最快的事情就是让这些领域变得不稳定。同步块可能更有效。我相信它们进入和退出比读取和写入易失性物品要花费更多,但是一旦进入,你可以以很少的额外成本修改一堆字段。