plspl
plspl

Reputation: 728

Java synchronization in web service

I have a java restful webservice program thats hosted on tomcat. In one of my web service methods, I load a big arraylist of objects (about 25,000 entries) from redis. This arraylist is updated once every 30 mins. There are multiple threads reading from this arraylist all the time. When, I update the arraylist I want to cause minimum disruption/delays since there could be other threads reading from it.

I was wondering what is the best way to do this? One way is to use synchronized keyword to the method that updates the list. But, the synchronized method has an overhead, since no threads can read while the update is going on. The update method itself could take few hundred millisecs since it involves reading from redis + deserialization.

class WebService {

 ArrayList<Entry> list = new ArrayList<Entry>();

    //need to call this every 30 mins.
    void syncrhonized updateArrayList(){
      //read from redis & add elements to list
    }

    void readFromList(){
      for(Entry e: list) {
       //do some processing
      }
    }

}

Updated the final solution: I ended up using no explicit synchronization primitives.

Upvotes: 2

Views: 4649

Answers (4)

plspl
plspl

Reputation: 728

Here is the solution I finally ended up with,

class WebService {

 // key = timeWindow (for ex:10:00 or 10:30 or 11:00), value = <List of entries for that timewindow>
 ConcurrentHashMap<String, List<Entry>> map= new ConcurrentHashMap<String, List<Entry>>();

    //have setup a timer to call this every 10 mins.
    void updateArrayList(){
     // populate the map for the next time window with the corresponding entries. So that its ready before we start using it. Also, clean up the expired entries for older time windows.

    }

    void readFromList(){
      list = map.get(currentTimeWindow)
      for(Entry e: list) {
       //do some processing
      }
    }

} 

Upvotes: 0

Misha
Misha

Reputation: 28133

Does it have to be the same List instance getting updated? Can you build a new list every 30 minutes and replace a volatile reference?

Something along these lines:

class WebService {
    private volatile List<Entry> theList;

    void updateList() {
        List<Entry> newList = getEntriesFromRedis();
        theList = Collections.unmodifiableList(newList);
    }

    public List<Entry> getList() {
        return theList;
    }
}

The advantage of this approach is that you don't have to do any other synchronization anywhere else.

Upvotes: 3

Adrian Shum
Adrian Shum

Reputation: 40036

A reader-writer lock (or ReadWriteLock in Java) is what you need.

A reader-writer lock will allow concurrent access for read operations, but mutually exclusive access for write.

It will look something like

class WebService {
    final ReentrantReadWriteLock listRwLock = new ReentrantReadWriteLock();
    ArrayList<Entry> list = new ArrayList<Entry>();

    //need to call this every 30 mins.
    void updateArrayList(){
        listRwLock.writeLock().lock();
        try {
            //read from redis & add elements to list
        } finally {
            listRwLock.writeLock().unlock()
        }
    }

    void readFromList(){
        listRwLock.readLock().lock();
        try {
            for(Entry e: list) {
                //do some processing
            }
        } finally {
            listRwLock.readLock().unlock()
        }

    }

}

Upvotes: 1

Danyal Sandeelo
Danyal Sandeelo

Reputation: 12391

ArrayList is not thread safe.. You must use vector List to make it thread safe.

You can also use Thread safe Array list by using Collections Api but I would recommend vector list since it already provides you what you want.

 //Use Collecions.synzhonizedList method
 List list = Collections.synchronizedList(new ArrayList());
 ...

 //If you wanna use iterator on the synchronized list, use it
 //like this. It should be in synchronized block.
 synchronized (list) {
   Iterator iterator = list.iterator();
   while (iterator.hasNext())
   ...
  iterator.next();
  ...
}

I would recommend you to through this: http://beginnersbook.com/2013/12/difference-between-arraylist-and-vector-in-java/

Upvotes: -1

Related Questions