2015-08-05 9 views
5

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.

risposta

0

Mi sembra che restituire l'elenco incFriendReq direttamente in getFriendReq sia una delle fonti del problema. Quando si utilizza java 8 e si esegue lo streaming di un elenco in un nuovo elenco, si sta solo effettuando una copia, quindi non vi sono aggiunte utili. In questo caso, il codice sul lato server dovrebbe funzionare anche utilizzando new ArrayList<>(me.getFriends()).

Verificherei che tutti gli accessi alla lista siano sincronizzati correttamente e che tu sappia dove e quando tale lista viene modificata.

+0

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

+0

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). –