2

I have a Java class that contains an ArrayList of transaction info objects that get queried and modified by different threads on a frequent basis. At a basic level, the structure of the class looks something like this (currently no synchronization is present):

class Statistics
{
    private List<TranInfo> tranInfoList = new ArrayList<TranInfo>();

    // This method runs frequently - every time a transaction comes in.
    void add(TranInfo tranInfo)
    {
        tranInfoList.add(tranInfo);
    }

    // This method acts like a cleaner and runs occasionally.       
    void removeBasedOnSomeCondition()
    {
        // Some code to determine which items to remove

        tranInfoList.removeAll(listOfUnwantedTranInfos);
    }

    // Methods to query stats on the tran info.
    // These methods are called frequently.
    Stats getStatsBasedOnSomeCondition()
    {
        // Iterate over the list of tran info
        // objects and return some stats
    }


    Stats getStatsBasedOnSomeOtherCondition()
    {
        // Iterate over the list of tran info
        // objects and return some stats
    }
}

I need to ensure that read/write operations on the list are synchronized correctly, however, performance is very important, so I don't want to end up locking in every method call (especially for concurrent read operations). I've looked at the following solutions:

CopyOnWriteArrayList

I've looked at the use of a CopyOnWriteArrayList to prevent ConcurrentModificationExceptions being thrown when the list is modified while iterating over it; the problem here is the copy required each time the list is modified... it seems too expensive given how often the list will be modified and the potential size of the list.

ReadWriteLock

A ReadWriteLock could be used to synchronize read/write operations while allowing concurrent read operations to take place. While this approach will work, it ends up resulting in a lot of synchronization code in the class (this isn't the end of the world though).


Are there any other clever ways of achieving this kind of synchronization without a big performance penalty, or are one of the above methods the recommended way? Any advice on this would be greatly appreciated.

6
  • How frequently is the list modified? How big is it? Commented May 13, 2013 at 19:16
  • ReadWriteLock is the correct solution IMO. If the mixing of concerns bothers you, insert a level of proxying. Commented May 13, 2013 at 19:17
  • Do you know this is problem because I wouldn't assume you are calling these methods often enough to cause a problem. i.e. is it 1K/s, 10K/s, 100K/s or 1M/s? Commented May 13, 2013 at 19:17
  • If you don't want locking in every method call, and you don't want to copy the whole list on each write, you'll need to abandon random ordered access for a List. Maybe a ConcurrentLinkedQueue? Commented May 13, 2013 at 19:37
  • It seems that you have exceeded the design intent for ArrayList. Perhaps you should consider another, more specialized, container. This sounds like a job for a concurrent queue or synchronizedList. Have you looked at those? Commented May 13, 2013 at 21:26

2 Answers 2

3

I'd use Collections.synchronizedList() until you know for sure that it is indeed the crucial performance bottle neck of your application (needless to say I doubt it is ;-)). You can only know for sure through thorough testing. I assume you know about "premature optimization"...

If then you strive to optimize access to that list I'd say ReadWriteLock is a good approach.

Sign up to request clarification or add additional context in comments.

Comments

0

Another solution that may make sense (especially under heavy read/write) is ConcurrentLinkedQueue (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html). It is a pretty scalable implementation under contention, based on CAS operations.

The one change that's required to your code is that ConcurrentLinkedQueue does not implement the List interface, and you need to abide by either the Iterable or the Queue type. The only operation you lose really is random access via index, but I don't see that being an issue in your access pattern.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.