Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Frage zu Collections.synchronizedMap

26 views
Skip to first unread message

Thomas Barth

unread,
Apr 26, 2011, 12:21:39 PM4/26/11
to
Hallo,
ich habe eine Server-Applikation mit zwei Threads. Der eine Thread führt
zusammengefasst Datenbankabfragen für die Clients aus, während der
andere Thread die Clients managed. Die Clients holen sich die Daten aus
den Objekten, die vom Datenbank-Thread gefüllt werden. Dies geschieht
hier in updateAgentData().

//aufgerufen vom Datenbank-Thread
private void updateAgentData() {
Iterator<Map.Entry<String, Agent>> it =
agent_map.entrySet().iterator();

Agent agent;
String agent_id = "";

while (it.hasNext()) {
Map.Entry<String, Agent> entry = it.next();

agent_id = entry.getKey();
agent = entry.getValue();

...mach was mit Objekt "agent"


Wenn sich genau zu diesem Zeitpunkt ein Client abmeldet, wird das Objekt
Agent über den Client-Thread während der Iteration gelöscht
(agent_map.remove(agent_id)). Obwohl ich die Map agent_map mit
synchronized angelegt habe,

private static Map<String, Agent> agent_map =
Collections.synchronizedMap(new HashMap<String, Agent>());

erhalte ich dennoch den Ausnahmefehler ConcurrentModificationException

Exception in thread "Timer-0" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:810)
at java.util.HashMap$EntryIterator.next(HashMap.java:851)
at java.util.HashMap$EntryIterator.next(HashMap.java:849)

Warum? Ich dachte, dass Modifikationen an einer Liste während einer
Iteration so verhindert werden?

Gruß, Thomas

Patrick Roemer

unread,
Apr 26, 2011, 12:36:55 PM4/26/11
to
Responding to Thomas Barth:

> private static Map<String, Agent> agent_map =
> Collections.synchronizedMap(new HashMap<String, Agent>());
>
> erhalte ich dennoch den Ausnahmefehler ConcurrentModificationException
>
> Exception in thread "Timer-0" java.util.ConcurrentModificationException
> at java.util.HashMap$HashIterator.nextEntry(HashMap.java:810)
> at java.util.HashMap$EntryIterator.next(HashMap.java:851)
> at java.util.HashMap$EntryIterator.next(HashMap.java:849)
>
> Warum? Ich dachte, dass Modifikationen an einer Liste während einer
> Iteration so verhindert werden?

Wie sollte das in der Praxis sinnvoll bewerkstelligt werden?

| It is imperative that the user manually synchronize on the returned
| map when iterating over any of its collection views:
|
| Map m = Collections.synchronizedMap(new HashMap());
| ...
| Set s = m.keySet(); // Needn't be in synchronized block
| ...
| synchronized(m) { // Synchronizing on m, not s!
| Iterator i = s.iterator(); // Must be in synchronized block
| while (i.hasNext())
| foo(i.next());
| }
[API-Doc zu Collections#synchronizedMap()]

Die bessere Loesung waere hier wohl ein interner Iterator - in Java mit
brauchbarer Syntax voraussichtlich um das Jahr 2058 zu haben. :/

Viele Gruesse,
Patrick

Thomas Barth

unread,
Apr 27, 2011, 7:47:32 AM4/27/11
to
Am 26.04.2011 18:36 schrieb Patrick Roemer:
>
> | It is imperative that the user manually synchronize on the returned
> | map when iterating over any of its collection views:
> |
> | Map m = Collections.synchronizedMap(new HashMap());
> | ...
> | Set s = m.keySet(); // Needn't be in synchronized block
> | ...
> | synchronized(m) { // Synchronizing on m, not s!
> | Iterator i = s.iterator(); // Must be in synchronized block
> | while (i.hasNext())
> | foo(i.next());
> | }
> [API-Doc zu Collections#synchronizedMap()]
>
> Die bessere Loesung waere hier wohl ein interner Iterator - in Java mit
> brauchbarer Syntax voraussichtlich um das Jahr 2058 zu haben. :/
>
> Viele Gruesse,
> Patrick

Danke funktioniert. Den Ausnahmefehler konnte ich nicht mehr provozieren.

Set<Map.Entry<String, Agent>> s = agent_map.entrySet();

synchronized (agent_map) {


Agent agent;
String agent_id = "";

Iterator<Map.Entry<String, Agent>> it = s.iterator();

while (it.hasNext()) {
Map.Entry<String, Agent> map = it.next();

agent_id = map.getKey();
agent = map.getValue();


Viele Grüße, Thomas

Sascha Broich

unread,
Apr 27, 2011, 8:11:01 AM4/27/11
to
On Wed, 27 Apr 2011 13:47:32 +0200, Thomas Barth wrote:

Etwas einfacher:

synchronized (agent_map) {
for(Map.Entry<String, Agent> entry:agent_map.entrySet()) {
String agent_id=entry.getKey();
Agent agent=entry.getValue();

//mach was mit Agent
}
}

Sascha Broich
--
Eine nicht ernstlich gemeinte Willenserklärung, die in
der Erwartung abgegeben wird, der Mangel der Ernstlichkeit
werde nicht verkannt werden, ist nichtig.
(§ 118 BGB - Mangel der Ernstlichkeit)

0 new messages