我有一個簡單的XO遊戲,其中有多個客戶端互相玩XO國際象棋。我建立了一個與每個連接的客戶端進行通信的服務器。 (當客戶端連接到服務器時,我創建一個新類(實現Runnable)處理該套接字,然後啓動線程...我有一個List存儲外部類中的所有客戶端)當客戶端想要啓動一個遊戲時,他使自己成爲一個新的服務器,並將該房間的信息(他的名字,IP地址,端口...)發送到服務器。而在服務器中,我有一個列表,將該房間添加到列表中,並將其發送給其他客戶端。Java套接字 - 更新實例變量線程列表
public class ServerController {
private ServerView view;
private ServerSocket myServer;
private int serverPort = 8881;
private List<ExchangeData> list;
private volatile List<Room> rooms;
public ServerController(ServerView view) {
this.view = view;
openServer(serverPort);
view.showMessage("TCP server is running...");
list = new ArrayList<ExchangeData>();
rooms = new ArrayList<Room>();
while (true) {
listening();
}
}
private void openServer(int portNumber) {
....
}
private void listening() {
try {
Socket clientSocket = myServer.accept();
ExchangeData ex = new ExchangeData(clientSocket);
Thread thread = new Thread(ex);
thread.start();
list.add(ex);
} catch (IOException e) {
System.out.print(e.toString());
}
}
class ExchangeData implements Runnable {
private Socket clientSocket;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private boolean run = true;
public ExchangeData(Socket socket) {
try {
clientSocket = socket;
oos = new ObjectOutputStream(clientSocket.getOutputStream());
ois = new ObjectInputStream(clientSocket.getInputStream());
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
public void closeConnection() {
.....
}
public void sendData(Object o) {
try {
oos.writeObject(o);
} catch (Exception ex) {
view.showMessage(ex.toString());
}
}
public void run() {
try {
while (run) {
Object data = ois.readObject();
if (data instanceof Object[]) {
Object[] o = (Object[]) data;
String s = o[0].toString();
if (s.equalsIgnoreCase("Open Room")) {
Room r = (Room) o[1];
String username = r.getUsername();
InetSocketAddress isa = r.getIsa();
**rooms.add(r);**
List<Room> l = new ArrayList<Room>(rooms);
for (ExchangeData ex : list) {
ex.sendData(username + " Open A room at : "
+ isa);
**ex.sendData(rooms);**
}
} else if (s.equalsIgnoreCase("Close Room")) {
Room room = (Room) o[1];
rooms.remove(room);
List<Room> l = new ArrayList<Room>(rooms);
for (ExchangeData ex : list) {
ex.sendData(l);
}
}
} else if (data instanceof String) {
String s = data.toString();
if (s.equalsIgnoreCase("Quit")) {
stopThread();
list.remove(this);
closeConnection();
}
}
}
} catch (Exception ex) {
try {
stopThread();
list.remove(this);
} catch (ExceptionInInitializerError e) {
e.printStackTrace();
}
}
}
}
}
問題是,當我執行rooms.add(R),其他線程似乎沒有看到, 「更新」。例如: 1)第一位玩家打開房間 - 房間大小爲1; 2)第二個玩家打開一個新房間 - 房間大小現在是2(我試圖在sendData(Object o)方法中添加一些代碼行,它在房間的大小上打印並且全部是2.但是當行ObjectoutputStream .write(o)被執行,它實際上寫入線程(第一個玩家)在之前保存的房間的值爲1. 如果我創建像List一樣的新列表l = new ArrayList(房間),就像我對「Closing Room 「然後發送這個,它工作,我不明白爲什麼?有人請向我解釋這個。對不起,我的英語不好:(
哇,非常感謝Nizet,我花了好幾天的時間來閱讀關於線程安全,併發等方面的知識,希望我可以爲你投票。 – user2747502