Jamal H
Jamal H

Reputation: 1084

Java making a copy of a list thread safe?

I have multiple threads running in a Java application, and all of them need to access the same list. Only one thread, however, actually needs to insert/delete/change the list, and the others just need to access it.

In the other threads, I want to make a copy of the list for me to use whenever I need to read it, but is there any way to do this in a thread safe way? If I had a method to copy the list element by element and the list changed, that would mess it up wouldn't it?

EDIT:

The list will not be deleted from very often, so would it work if I just copied it normally and caught exceptions? If the list grew in the middle of the copy and I missed it, it wouldn't really make a difference to functionality

Upvotes: 2

Views: 2385

Answers (6)

starikoff
starikoff

Reputation: 1650

Depending on your particular usage, you might benefit from one of these:

  1. If you don't really need random access, use ConcurrentLinkedQueue. No explicit synchronization required.
  2. If you don't need random access for writes but only need it for reads, use ConcurrentLinkedQueue for writes and copy it to a list from time to time if changes were made to the queue (in a separate thread), give this list to "readers". Does not require explicit synchronization; gives a "weakly consistent" read view.
  3. Since your writes come from one thread, the previous could work with 2 lists (e.g. the writing thread will copy it to the "reading view" from time to time). However, be aware that if you use an ArrayList implementation and require random access for writes then you are looking at constant copies of memory regions, not good even in the absence of excessive synchronization. This option requires synchronization for the duration of copying.
  4. Use a map instead, ConcurrentHashMap if you don't care about ordering and want O(1) performance or ConcurrentSkipListMap if you do need ordering and are ok with O(logN) performance. No explicit synchronization required.

Upvotes: 0

Jamal H
Jamal H

Reputation: 1084

I decided to solve this by having a separate thread that handles the thread, with BlockingQueue for the other threads to submit to if they want to write to the list, or get from the list. If they wanted to write to the list it would submit an object with the content that they wanted to write, and if they wanted to read, it would submit a Future that the thread with the list would populate

Upvotes: 0

gati sahu
gati sahu

Reputation: 2626

You can use CopyOnWriteArrayList which is thread safe ,but it create new one on every update process.

Or you can use readWriteLock so when update use no one can read while multiple thread can read simultaneously .

Upvotes: 0

Laurentiu Motoonu
Laurentiu Motoonu

Reputation: 19

Hmm, so I think that what are you looking for is called CopyOnWriteArrayList.

CopyOnWriteArrayList - 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.

Ref: CopyOnWriteArrayList

Upvotes: 1

Mykola Yashchenko
Mykola Yashchenko

Reputation: 5361

You can use CopyOnWriteArrayList for your purpose.

CopyOnWriteArrayList is a concurrent Collection class introduced in Java 5 Concurrency API along with its popular cousin ConcurrentHashMap in Java.

As name suggest CopyOnWriteArrayList creates copy of underlying ArrayList with every mutation operation e.g. add or set. Normally CopyOnWriteArrayList is very expensive because it involves costly Array copy with every write operation but its very efficient if you have a List where Iteration outnumber mutation e.g. you mostly need to iterate the ArrayList and don't modify it too often.

With this collection, you shouldn't create a new instance every time. You should have only one object of this and it will work.

Upvotes: 3

Akash
Akash

Reputation: 593

Use Collections.synchronizedList().

Example :

Collections.synchronizedList(new ArrayList<YourClassNameHere>())

Upvotes: -1

Related Questions