简体   繁体   中英

Consume elements from ConcurrentHashMap

I use a ConcurrentHashMap to buffer messages for a websocket.

Every 200ms the buffer is sent in one JSON String. afterwards I want to remove the entry from the Map.

This is not safe I guess, because during the foreach there might come new messages to the buffer.

String sendString;
for(String msg : buffer.values()){
    sendString += msg;
}
ws.send(sendString);
buffer.clear();

How could I safely remove the Elements?

Map#remove() returns value that exists in map prior to removal. In ConcurrentHashMap this is performed atomically, so you can safely consume the result:

StringBuilder sendString = new StringBuilder();
for (String key : buffer.keySet()) {
    String s = buffer.remove(key);
    if (s != null)
        sendString.append(s);
}  

You need to check the key and value.

StringBuilder sendString = new StringBuilder();
for (Map.Entry<String, String> entry : buffer.entrySet()) {
    sendString.append(entry.getValue());
    buffer.remove(entry.getKey(), entry.getValue()); // only remove a matching value
}

Use iterator explicitly:

StringBuilder result = new StringBuilder();
for (Iterator<String> it = buffer.values().iterator(); it.hasNext(); ) {
    result.append(it.next());
    it.remove();
}

Put your entire method block in a synchronized block. No other thread can write to the map while this code is being executed.

synchronized(buffer){
    String sendString;
    for(String msg : buffer.values()){
        sendString += msg;
    }
    ws.send(sendString);
    buffer.clear();
}

synchronized(buffer){
   buffer.put(key, msg);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM