Java Concurrency - Concurrent Collections
Data structures are a basic element in programming. Almost every program uses one or more types of data structures to store and manage their data. Java API provides the Java Collections framework that contains interfaces, classes, and algorithms, which implement a lot of different data structures that you can use in your programs.
When you need to work with data collections in a concurrent program, you must be very careful with the implementation you choose. Most collection classes are not ready to work with concurrent applications because they don't control the concurrent access to its data. If some concurrent tasks share a data structure that is not ready to work with concurrent tasks, you can have data inconsistency errors that will affect the correct operation of the program. One example of this kind of data structures is the ArrayList class.
Java provides data collections that you can use in your concurrent programs without any problems or inconsistency. Basically, Java provides two kinds of collections to use in concurrent applications:
- Blocking collections: This kind of collection includes operations to add and remove data. If the operation can't be made immediately, because the collection is full or empty, the thread that makes the call will be blocked until the operation can be made.
- Non-blocking collections: This kind of collection also includes operations to add and remove data. If the operation can't be made immediately, the operation returns a null value or throws an exception, but the thread that makes the call won't be blocked.
ConcurrentLinkedDeque
An unbounded concurrent deque based on linked nodes. Concurrent insertion, removal, and access operations execute safely across multiple threads. A ConcurrentLinkedDeque is an appropriate choice when many threads will share access to a common collection. Like most other concurrent collection implementations, this class does not permit the use of null elements.
Method Summary
public void addFirst(E e)
Inserts the specified element at the front of this deque. As the deque is unbounded, this method will never throw IllegalStateException.
public void addLast(E e)
Inserts the specified element at the end of this deque. As the deque is unbounded, this method will never throw IllegalStateException.
public boolean offerFirst(E e)
Inserts the specified element at the front of this deque. As the deque is unbounded, this method will never return false.
public boolean offerLast(E e)
Inserts the specified element at the end of this deque. As the deque is unbounded, this method will never return false.
public E peekFirst()
Retrieves, but does not remove, the first element of this deque, or returns null if this deque is empty.
public E peekLast()
Retrieves, but does not remove, the last element of this deque, or returns null if this deque is empty.
public E getFirst()
Retrieves, but does not remove, the first element of this deque. This method differs from peekFirst only in that it throws an exception if this deque is empty.
public E getLast()
Retrieves, but does not remove, the last element of this deque. This method differs from peekLast only in that it throws an exception if this deque is empty.
public E pollFirst()
Retrieves and removes the first element of this deque, or returns null if this deque is empty.
public E pollLast()
Retrieves and removes the last element of this deque, or returns null if this deque is empty.
public E removeFirst()
Retrieves and removes the first element of this deque. This method differs from pollFirst only in that it throws an exception if this deque is empty.
public E removeLast()
Retrieves and removes the last element of this deque. This method differs from pollLast only in that it throws an exception if this deque is empty.
ConcurrentLinkedQueue
An unbounded thread-safe queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. A ConcurrentLinkedQueue is an appropriate choice when many threads will share access to a common collection. Like most other concurrent collection implementations, this class does not permit the use of null elements.
Method Summary
public boolean add(E e)
Inserts the specified element at the tail of this queue. As the queue is unbounded, this method will never throw IllegalStateException or return false.
public boolean offer(E e)
Inserts the specified element at the tail of this queue. As the queue is unbounded, this method will never return false.
public E poll()
Retrieves and removes the head of this queue, or returns null if this queue is empty.
public E peek()
Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
public boolean remove(Object o)
Removes a single instance of the specified element from this queue, if it is present. More formally, removes an element e such that o.equals(e), if this queue contains one or more such elements. Returns true if this queue contained the specified element (or equivalently, if this queue changed as a result of the call).
public int size()
Returns the number of elements in this queue. If this queue contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.
Beware that, unlike in most collections, this method is NOT a constant-time operation. Because of the asynchronous nature of these queues, determining the current number of elements requires an O(n) traversal. Additionally, if elements are added or removed during execution of this method, the returned result may be inaccurate. Thus, this method is typically not very useful in concurrent applications.
public boolean contains(Object o)
Returns true if this queue contains the specified element. More formally, returns true if and only if this queue contains at least one element e such that o.equals(e).
LinkedBlockingDeque
An optionally-bounded blocking deque based on linked nodes. The optional capacity bound constructor argument serves as a way to prevent excessive expansion. The capacity, if unspecified, is equal to Integer.MAX_VALUE. Linked nodes are dynamically created upon each insertion unless this would bring the deque above capacity.
LinkedBlockingQueue
An optionally-bounded blocking queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.
ArrayBlockingQueue
A bounded blocking queue backed by an array. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue.
This is a classic "bounded buffer", in which a fixed-sized array holds elements inserted by producers and extracted by consumers. Once created, the capacity cannot be changed. Attempts to put an element into a full queue will result in the operation blocking; attempts to take an element from an empty queue will similarly block.
This class supports an optional fairness policy for ordering waiting producer and consumer threads. By default, this ordering is not guaranteed. However, a queue constructed with fairness set to true grants threads access in FIFO order. Fairness generally decreases throughput but reduces variability and avoids starvation.
PriorityBlockingQueue
An unbounded blocking queue that uses the same ordering rules as class PriorityQueue and supplies blocking retrieval operations. While this queue is logically unbounded, attempted additions may fail due to resource exhaustion (causing OutOfMemoryError). This class does not permit null elements. A priority queue relying on natural ordering also does not permit insertion of non-comparable objects (doing so results in ClassCastException).
This class and its iterator implement all of the optional methods of the Collection and Iterator interfaces. The Iterator provided in method iterator() is not guaranteed to traverse the elements of the PriorityBlockingQueue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()). Also, method drainTo can be used to remove some or all elements in priority order and place them in another collection.
Operations on this class make no guarantees about the ordering of elements with equal priority. If you need to enforce an ordering, you can define custom classes or comparators that use a secondary key to break ties in primary priority values.