Ho un problema. La mia convinzione è che abbia qualcosa a che fare con la concorrenza o la sincronizzazione dei thread, anche se non riesco a capire cosa sta succedendo.Corrispondenza ArrayList tra connessioni socket
Questa è la descrizione del flusso di dati per l'oggetto FriendRequestList
.
Dal lato client inviamo una richiesta di amicizia a un altro utente (lavoratore). Quindi inviamo la richiesta e aggiungiamo il nostro nome utente al loro elenco User.incFriendReq
. L'istanza è un ArrayList
solo per riferimento piacevole.
Così ora inviamo la richiesta al server per ricevere la nostra lista di richieste di amicizia (FriendRequestList.java
).
Quindi ora il problema. Se utilizzo questo codice sotto l'utente non vedrà la richiesta di amicizia prima che termini la sua connessione (logout), che chiuderà la connessione. Quando accederà, vedrà solo la richiesta nella sua lista.
codice lato server:
... Worker.java ...
private Object getFriendRequests() {
User me = Data.getUser(myUserName);
if (me == null) {
return new NoSuchUserException(); // Don't worry about it ;)
}
return new FriendRequestList(me.getFriendReq());
}
... User.java ...
private List<String> incFriendReq;
public List<String> getFriendReq() {
return incFriendReq;
}
lato client
... Comunicazioni n.java ...
public FriendRequestList getRequests() {
sendObject(new GetRequests());
return inputHandler.containsRequests();
}
... MessageListener.java ...
public void run() {
...
FriendRequestList requests = communication.getRequests();
update(requestList, requests);
// Here we have the problem. requests.size is never different from 0
}
Come mai, se aggiorno Worker.java
per fare questo, invece:
private Object getFriendRequests() {
User me = Data.getUser(myUserName);
if (me == null) {
return new NoSuchUserException();
}
return new FriendList(me.getFriends().stream().collect(Collectors.toList()));
}
L'istante l'altro utente richiede la mia amicizia, vedo la richiesta sulla mia lista. Cosa dà? Mi sembra che il dato sottostante non sia aggiornato, condizioni di gara o qualcosa del genere. Ma la correzione è il modo in cui recupero i dati sul lato server, utilizzando uno stream.
Per favore qualcuno spieghi e anche come sarebbe stato fatto in Java 7 prima che i flussi risolvessero il mio, per me, un problema curioso.
Su una nota
voglio aggiungere che gli utenti sono collocati all'interno di un LinkedBlockingDeque
e recuperare dall'oggetto Data
, una risorsa condivisa per i lavoratori.
La cosa affascinante di questo codice è che mentre eseguo il debug della lista che ottengo da 'getFriendReq' è effettivamente di dimensione uno. Ma quando ricevo l'oggetto dall'altra parte è di dimensione zero. – miniwolf
Mi sembra che lo stato dell'elenco sul lato server non venga gestito correttamente. L'elenco potrebbe essere di dimensione zero perché una copia obsoleta dell'elenco era ancora in giro da qualche parte da restituire ma non era la stessa lista del valore che si sta guardando (controllare l'ID oggetto nel debugger per verificare) o c'è una concorrenza problema relativo alla visibilità della memoria che non espone i dati mutati attraverso i thread (assicurarsi che tutti gli accessi all'elenco siano sincronizzati sullo stesso blocco). –