简体   繁体   中英

looping over static Set- java

I have in my code:

public static Set<Long> workItemsForTasks = new HashSet<Long>();

It's a web application, and during the code the users can add new items to the map - and I add in the code like this:

WorkflowOperations.workItemsForTasks.add(workItem.getId());

Once the workflow reaches a specific code, I loop over the map like this:

 Iterator workItemsIter = service.workItemsForTasksToBMS.iterator();
   while (workItemsIter.hasNext()) {
workItemsIter.remove();

    ...
    }

My question is:

Once I get the iterator - if another user added a new item to the map (since it's not in the same internet page) - will it influence the map while I loop over it? Or retrieving the iterator ensures me that it holds the map size up to the time that the looping started?

EDITED

It's a web application that accepts different web service calls.

In Call A the users might add data that in Call BI need to handle.

So I defined a singleton class (via spring bean) which holds the Set of data that I need to handle (the data is numbers) and I modify the Set each time that I have web service Call A. once the user asks for web service Call B - I have to collect the data so far and execute something with it.

Is the set being accessed concurrently from multiple threads?

If it all happens on one thread, then what you're doing is fine.

However, if there is concurrent access, then you're doing two things wrong. First, HashSet is not thread-safe. Second, modifying a HashSet while iterating over it (except through an Iterator ) is wrong, and will (hopefully!) produce a ConcurrentModificationException .

You might address this by considering classes in java.util.concurrent , or you could also add some of your own synchronization to your case. You could synchronize access to the set, and when you need to remove stuff from it, do it all at once.

private static void doMyStuff() {
    Set<Long> myWorkingSet;
    synchronized (workItemsForTasks) {
        myWorkingSet = new HashSet(workItemsForTasks);
        workItemsForTasks.clear();
    }
    for (long x : myWorkingSet) {
        // do something
    }
}

If you do something like this, you should hide workItemsForTasks behind access methods in your class so you can guarantee correct synchronization.

static state is generally a bad thing. every time you see it, be wary

this code will be executed in a multithreaded environment, so what you have written will not work - you will get ConcurrentModificationException

you dont have a domain model! sets of longs are not meaningful. try to express what is going on in terms of a higher level abstraction.

you are not following "tell dont ask", and specifically violating LoD-F (http://pragprog.com/articles/tell-dont-ask) - which is a way of saying yur code will soon be difficult to follow who does what.

alternatively, to hack in something that will mostly work, use a CopyOnWriteArraySet .

First of all, am assuming when you said map, you actually meant Set . As per Java Doc ,

Note that this implementation is not synchronized. If multiple threads access a hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the set. If no such object exists, the set should be “wrapped” using the Collections.synchronizedSet method. This is best done at creation time, to prevent accidental unsynchronized access to the set:

Thread safe implementation of HashSet would be like:

Set s = Collections.synchronizedSet(new HashSet(...));

As far as Iterator goes, It is impossible to make any hard guarantees in the presence of unsynchronized concurrent modification, so you should manually synchronize on the returned set when iterating over it else the results would be non-deterministic.

Set workItemsForTasks = Collections.synchronizedSet(new HashSet());
synchronized(workItemsForTasks) {
Iterator workItemsIter  = workItemsForTasks.iterator(); //Must be in synchronized block
while (workItemsIter.hasNext())
    //Do Something
}

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