The concurrent collection APIs, apart from the Java Collection API, are a set of collections APIs that are designed and optimized specifically for synchronized multithreaded access. They are grouped under the java. util. concurrent package.
Concurrency is the ability to run several programs or several parts of a program in parallel. If a time consuming task can be performed asynchronously or in parallel, this improves the throughput and the interactivity of the program. A modern computer has several CPU's or several cores within one CPU.
The main reason for this slowness is locking; synchronized collections lock the whole collection e.g. whole Map or List while concurrent collection never locks the whole Map or List. They achieve thread safety by using advanced and sophisticated techniques like lock stripping.
Concurrency is the ability to run several or multi programs or applications in parallel. The backbone of Java concurrency is threads (a lightweight process, which has its own files and stacks and can access the shared data from other threads in the same process).
ConcurrentLinkedQueue
If you don't care about having index-based access and just want the insertion-order-preserving characteristics of a List, you could consider a java.util.concurrent.ConcurrentLinkedQueue
. Since it implements Iterable, once you've finished adding all the items, you can loop over the contents using the enhanced for syntax:
Queue<String> globalQueue = new ConcurrentLinkedQueue<String>();
//Multiple threads can safely call globalQueue.add()...
for (String href : globalQueue) {
//do something with href
}
There is a concurrent list implementation in java.util.concurrent. CopyOnWriteArrayList in particular.
Disclaimer : This answer was published in 2011, before JDK 5, and before much advanced and optimal concurrent APIs. So, while the following will work, it is not the best option.
You can very well use Collections.synchronizedList(List) if all you need is simple invocation synchronization:
List<Object> objList = Collections.synchronizedList(new ArrayList<Object>());
Because the act of acquiring the position and getting the element from the given position naturally requires some locking (you can't have the list have structural changes between those two operations).
The very idea of a concurrent collection is that each operation on its own is atomic and can be done without explicit locking/synchronization.
Therefore getting the element at position n
from a given List
as an atomic operation doesn't make too much sense in a situation where concurrent access is anticipated.
You have these options:
Collections.synchronizedList()
: you can wrap any List
implementation (ArrayList
, LinkedList
or a 3rd-party list). Access to every method (reading and writing) will be protected using synchronized
. When using iterator()
or enhanced for loop, you must manually synchronize the whole iteration. While iterating, other threads are fully blocked even from reading. You can also synchronize separately for each hasNext
and next
calls, but then ConcurrentModificationException
is possible.
CopyOnWriteArrayList
: it's expensive to modify, but wait-free to read. Iterators never throw ConcurrentModificationException
, they return a snapshot of the list at the moment of iterator creation even if the list is modified by another thread while iterating. Useful for infrequently updated lists. Bulk operations like addAll
are preferred for updates - the internal array is copied less many times.
Vector
: very much like synchronizedList(new ArrayList<>())
, but iteration is synchronized too. However, iterators can throw ConcurrentModificationException
if the vector is modified by another thread while iterating.
Other options:
Queue
or Deque
might be an alternative if you only add/remove at the ends of the list or iterate it. Queue
allows only adding at one end and removing from the other end, Deque
allows adding and removing on both ends. There's no access by index. There are multiple implementations with better concurrency properties than any List
can provide. Look at "All Known Implementing Classes" in the Queue javadoc, those implementations that are in the java.util.concurrent
package are concurrent. You can also have a look at JCTools, it contains faster queue implementations specialized for single consumer or single producer.Collections.unmodifiableList()
: wait-free, thread-safe, but non-modifiableList.of
& List.copyOf
: Another non-modifiable list in Java 9 and later.CopyOnWriteArrayList is 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.
CopyOnWriteArrayList is a concurrent alternative of synchronized List implements List interface and its part of java.util.concurrent packageand its a thread-safe collection.
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
CopyOnWriteArrayList is fail-safe and doesn't throw ConcurrentModificationException when underlying CopyOnWriteArrayList is modified during Iteration use a separate copy of ArrayList.
This is ordinarily too costly because copy array involved every update operation a cloned copy will be created. CopyOnWriteArrayList is the best choice only for frequent read operation.
/**
* Returns a shallow copy of this list. (The elements themselves
* are not copied.)
*
* @return a clone of this list
*/
public Object clone() {
try {
@SuppressWarnings("unchecked")
CopyOnWriteArrayList<E> clone =
(CopyOnWriteArrayList<E>) super.clone();
clone.resetLock();
return clone;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/CopyOnWriteArrayList.html
https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With