简体   繁体   中英

Java concurrent access on list with just 1 writer and many objects

i have the following situation:

I need a list or whatever to store many many objects.

They all are generated by one class that contains the list itself.

Now i have at least one (but perhaps more) classes in other threads that always wanna start with the first object in list and take perodically (20ms-100ms) the next one.

The list is growing by time. At the end there can be up to 300k objects. (one of this objects can contain up to 50 ints or sth like that)

Is the ConcurrentLinkedQueue with own iterator implementation the right way to go? Own iterator is needed to deny remove option?

If you have 1 writer and multiple readers that are iterating through the list as it grows then yes, I would absolutely recommend using the ConcurrentLinkedQueue . It is designed for multiple concurrent operations on the queue.

You cannot use Collections.synchronizedList because the Javadocs specifically warn about iterating at modifications to the list:

It is imperative that the user manually synchronize on the returned list when iterating over it:

Obviously iterators are the way to go with ConcurrentLinkedQueue as the queue gets huge (300k items). Be careful of Queue methods that cause your program to run through the entire queue looking for entries and the like.

Another option to consider is the ConcurrentSkipListMap available in Java 6+. Although it is a log2 lookup map, it also has ordered entries so iterating is the same as queue. This allows you to do map and queue operations on the collection concurrently. Skip-lists++.

Edit:

Own iterator is needed to deny remove option?

If you are asking if you need to override the iterator to not allow removals then yes you do. You might consider extending the entire Queue to return your own custom delegating iterator and to block Queue.remove(...) as well.

Since there's only one writer and many readers, you might consider using CopyOnWriteArrayList . From the documentation:

A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

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. The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException .

Edit: As Gray points out the sheer number of inserts makes this solution prohibitive - I'd go with his solution.

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