我现在真的很迷茫。
我有这个Server
,它为每个连接的客户端创建一个新Thread
,所以它看起来像这样:
Server.java
...
( new ServerReceiver( toClient, this.connectedPlayersObject ) ).start();
...
(toClient
是一个ObjectOutputStream
,this.connectedPlayerObject
是一个操纵数组列表的对象)
这被称为
...
Socket socket = this.serverSocket.accept();
this.connectedPlayersObject.add( thisPlayer );
...
无论如何,我的服务器.java一切正常,但在我上面显示的那个线程中,我有这个:
ServerSender.java ( Thread )
...
private ConnectedPlayers CPO;
private ArrayList<Players> CPL;
public ServerSender( ObjectOutputStream _toClient, ConnectedPlayers _CPO ) {
super( "ServerSender" );
this.CPL = _CPO.get(); // returns the whole ArrayList that I have in this moment
this.CPO = _CPO // remember the object
}
public void run() {
while( true ) {
// here if the Server which starts the Thread is adding something to
// this.CPO's ArrayList, this.CPL gets that element inside of it too, why?
this.printCPLs( this.CPL, this.CPO.get() ); // Prints both ArrayLists Nicely
}
}
...
他们总是打印相同的更新的 ArrayList,即使我从不更新this.CPL
!
正如您在上面看到的,Server.java,每次客户端连接时,它都会将客户端添加到ConnectedPlayers
对象中的ArrayList
中,因此在线程中,我希望在调用.get();
时获得正确的ArrayList
,但我在私有属性this.CPL
和this.CPO.get();
上都获得了正确/更新的元素, 所以我无法弄清楚ArrayList
何时实际上从一个状态更改为另一个状态
编辑:对象女巫操纵ArrayList(CPO/connectedPlayersObject):
ConnectedPlayers.java
public class ConnectedPlayers implements Serializable {
private static final long serialVersionUID = -3225902114667506709L;
private ArrayList<Player> connectedPlayers;
public ConnectedPlayers() {
this.connectedPlayers = new ArrayList<Player>();
}
public synchronized void add( Player _player ) { this.connectedPlayers.add( _player ); this.notifyChange(); }
public ArrayList<Player> get() { return this.connectedPlayers; }
private void notifyChange() { }
}
所有代码都保留对同一ArrayList
对象的引用,因为您从不创建它的副本。因此,当代码的一部分将对象添加到ArrayList
时,它对代码中存储对同一ArrayList
的引用的其他位置可见。
如果要创建ArrayList
的副本,请使用 new ArrayList<Player>(originalList)
。
使用线程的事实在这里无关紧要;Java 中的线程共享相同的内存空间并可以访问相同的对象。将对象分配给线程属性不会自动创建该对象的副本。