Domanda

usavo HashMap prima come

   public Map<SocketChannel, UserProfile> clients = new HashMap<SocketChannel, UserProfile>();

Ora che ho passato a ConcurrentHashMap per evitare blocchi sincronizzati e problemi ora sto vivendo il mio server è pesantemente caricato con 200-400 client concorrenti al secondo, che è destinato a crescere nel corso del tempo.

, che ora assomiglia a questo

public ConcurrentHashMap<SocketChannel, UserProfile> clients = new ConcurrentHashMap<SocketChannel, UserProfile>();

Il mio design del server funziona in questo modo. Ho un thread di lavoro (s) per l'elaborazione di grandi quantità di pacchetti. Ogni pacchetto viene controllato con un sub-routine di packetHandler (non Parte della discussione) praticamente qualsiasi client può chiamare in qualsiasi momento è quasi come statica, ma non lo è.

Tutto il mio server è principalmente thread singolo ad eccezione della porzione di elaborazione di pacchetti.

In ogni modo così quando qualcuno usa un comando come contare tutti i clienti on-line e ottenere alcune informazioni da loro.

E 'anche possibile che i clienti possono ottenere scollegato e rimosso dal ConcurrentHashMap , mentre il conteggio è in corso (che fa sì che i miei problemi).

Inoltre vorrei aggiungere del codice qui.

                int txtGirls=0;
                int vidGirls=0;
                int txtBoys=0;
                int vidBoys=0;
                Iterator i = clients.values().iterator();
                while (i.hasNext()) {
                    UserProfile person = (UserProfile)i.next();
                    if(person != null) {
                        if(person.getChatType()) {
                            if(person.getGender().equals("m"))
                                vidBoys++;
                            else //<-- crash occurs here.
                                vidGirls++;
                        } else if(!person.getChatType()) {
                            if(person.getGender().equals("m"))
                                txtBoys++;
                            else
                                txtGirls++;
                        }
                    }
                }

Voglio dire, naturalmente, ho intenzione di risolvere il problema con l'aggiunta di un Exception try-catch all'interno del Iterator di saltare questi clienti nulli.

Ma quello che non capisco se i controlli di cui sopra, se (persona! = Null) non dovrebbero automaticamente il codice nidificato funziona ..

se non vuol dire che ha ottenuto rimosso mentre era iterazione che dovrebbe essere impossibile, dal momento che del thread WTF sicuro?

Che cosa devo fare? o è try-catch Eccezione il modo migliore?

Questa è l'eccezione

java.lang.NullPointerException
    at Server.processPackets(Server.java:398)
    at PacketWorker.run(PacketWorker.java:43)
    at java.lang.Thread.run(Thread.java:636)

I processPackets contiene il codice di cui sopra. e il commento indica il numero di linee #

Grazie per illuminarmi.

È stato utile?

Soluzione

Hai bisogno di leggere i javadoc per la ConcurrentHashMap.values() metodo, prestando particolare attenzione a questa descrizione di come l'iteratore per la raccolta values() funziona:

  

"La vista è iteratore è un 'debolmente coerente' iteratore che non potrà mai gettare ConcurrentModificationException, e le garanzie di attraversare gli elementi come esistevano sulla costruzione del iteratore, e può (ma non sono garantite a) riflettere eventuali modifiche successive alla costruzione. "

L'iteratore non ti dà un'istantanea coerente dello stato della collezione valori, ma è thread-safe , e la gamma prevista di comportamenti è chiaramente specificato .

Se si desidera un'implementazione di Map che fornisce un'istantanea coerente dei valori (o le chiavi o voci) nella mappa e vi permette di iterare in concomitanza con le modifiche, si avrà probabilmente bisogno di creare un Custom Map involucro di classe (che copia le collezioni atomicamente) ... o un costume implementazione vera e propria mappa. Entrambi sono suscettibili di essere molto più lento di un ConcurrentHashMap per il vostro caso d'uso.

Altri suggerimenti

java.util.concurrent.ConcurrentHashMap non consentono valore nullo. Così, controllo nullo (persona! = Null) nel codice non è necessaria.

Se si desidera negare modifica della mappa, mentre l'iterazione, è necessario utilizzare blocco di sincronizzazione nel codice sopra e tutti i codici di un'operazione di modifica.

non vedo niente di sbagliato con il codice. Poiché è improbabile che l'incidente si verifica effettivamente al else, è probabile che il metodo getGender() sta tornando null.

È possibile che non si può avere la mappa ottenere modificato mentre si sta scorrendo essa. Se questo è il caso si consiglia di ottenere i valori e le chiavi in ??una raccolta differenziata e Scorrere che, come sarà immutabile.

Non sarà perfetto, ma l'altra opzione è quella di estendere ConcurrentHashMap e quando viene aggiunto o rimosso qualcosa che aggiornare queste quattro variabili, in modo da non dovete scorrere l'intero elenco di volta in volta, come che sembra uno spreco di cicli di cPU.

Qui ci sono un paio di link che possono essere utili:

Questa ne parla un po 'del fatto che il miglioramento della concorrenza è a causa della distensione di alcune promesse. http://www.ibm.com/developerworks/java/library/ j-jtp07233.html

proprietà consistenza memoria spiegato: http: // download-llnw.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top