aspose file tools*
The moose likes Java in General and the fly likes Concurrent Modification Exception: CopyOnWriteArrayList or ArrayList.Clone() Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Concurrent Modification Exception: CopyOnWriteArrayList or ArrayList.Clone()" Watch "Concurrent Modification Exception: CopyOnWriteArrayList or ArrayList.Clone()" New topic
Author

Concurrent Modification Exception: CopyOnWriteArrayList or ArrayList.Clone()

Raghav Viswanathan
Greenhorn

Joined: Apr 26, 2012
Posts: 26

Hello Greenhorns,

few days back I faced an exception "java.util.ConcurrentModificationException"

We get this error similar to the scenario desribed below



The catch is that I have say a global list where I keep adding values when there is a change of property.

The way to solve this would be to
1. Clone the global list and use the cloned list for iteration
2.Use CopyOnWriteArrayList

I presonally prefer the CopyOnWriteArrayList because,

It creates a copy only when we would run into Concurrent modification

But am not able to substantiate my claim. Could anyone please help out on the understanding of the best solution and why one is better than the other?.


Better late than never.
Tony Docherty
Bartender

Joined: Aug 07, 2007
Posts: 2316
    
  49
But am not able to substantiate my claim. Could anyone please help out on the understanding of the best solution and why one is better than the other?.

The API docs for CopyOnWriteArrayList say:

"This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads."

So if you do many traversals and not many modifications it may be suitable and the other hand if you do many modifications and not many traversals it probably isn't.
Personally I wouldn't expose the list to other objects and so I would be able to suitable provide synchronization within the declaring class. There are many ways of doing this and the most efficient depends on the amount of data in your list and how you predominantly use the list. If performance is of the essence then you will probably have to try a few solutions and use a profiler to determine which is the most efficient.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39409
    
  28
Why on earth are you using the add method while you have an Iterator object in scope?
Raghav Viswanathan
Greenhorn

Joined: Apr 26, 2012
Posts: 26

Thanks Tony for your Reply.

Campbell Ritchie,

The following is a scenario that closely represents the way its implemented.

1. I have a global list of String (Screen field names for which some modfication has happened)
1.1 In a scenario, I have a String (StringObject1) which has been modified by the user on screen.
1.2 The modified element has a rule that suggests that if StringObject1= "Some Value" then StringObject2 will take "New Value".
1.3 In this case First, the list of modified element (global list that is maintained) is first iterated and each element in the list is processed to check for rules.
1.4 The Rule in Point 1.2 is triggered, thus modifying the value of StringObject2.
1.5 When ever a value is modified, the element is added to the global list.
1.6 at the next point of next iteration I run into ConcurrentMod.

I know this sounds silly and would be complex. If at all this needs to be refactored, it would mean a complete redesign. The fix to this problem seems to be either CopyOnWrite or Clone. Please suggest.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39409
    
  28
You don’t need to refactor anything. You simply need to use the Iterator correctly. If you need to add something, use a for loop rather than an Iterator.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39409
    
  28
Are you sure you won’t end up adding "3"s until you run out of memory?
Raghav Viswanathan
Greenhorn

Joined: Apr 26, 2012
Posts: 26

Campbell Ritchie wrote:Are you sure you won’t end up adding "3"s until you run out of memory?


I dont think so . Because,
1. (for ArrayList) :the Iterator when it was created will have a length of 5 and new additions will cause Concurrentmodification

2. For CopyOnWriteArrayList: : The iterator retains a copy and when calling add, a new copy of array list is created and on that the add is performed. It does not affect the arraylist object associated to the iterator

The Code looks like this.




the output for the code would be ,


List Value:1
My Old List >>>>>>>>>>> [1, 2, 3, 4, 5]
List Value:2
My Old List >>>>>>>>>>> [1, 2, 3, 4, 5]
List Value:3
My Old List >>>>>>>>>>> [1, 2, 4, 5, 3]
List Value:4
My Old List >>>>>>>>>>> [1, 2, 4, 5, 3]
List Value:5
My Old List >>>>>>>>>>> [1, 2, 4, 5, 3]


If you need to add something, use a for loop rather than an Iterator
.
I did not understand this part. becasue even if i use a for-loop instead of an iterator, I would end up at ConcurrentModification error.

Thanks and regards,
Raghav.V
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39409
    
  28
No Iterator, no exception. Iterate up to original size only. If you are deleting, you can use n-- to shorten the loop.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Concurrent Modification Exception: CopyOnWriteArrayList or ArrayList.Clone()