Mastering Thread‑Safe Java Collections: Vector, ConcurrentHashMap, and Blocking Queues
This guide explains why standard Java collections are not thread‑safe, introduces their concurrent counterparts such as Vector, ConcurrentHashMap, and various BlockingQueue implementations, and provides concrete code examples and usage patterns for safe multi‑threaded programming.
Thread‑Safe Collection Classes in Java
Java’s core collection framework provides many data structures, but most (e.g., ArrayList, HashMap) are not safe for concurrent access. When multiple threads modify a collection, data corruption or unexpected exceptions can occur. The following classes offer thread‑safe alternatives with the same API.
List – Vector
Vectorimplements java.util.List like ArrayList, but every mutating method is synchronized, guaranteeing thread safety.
Add (add)
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}Add All (addAll)
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c) {
if (add(e)) modified = true;
}
return modified;
}Remove by object
public boolean remove(Object o) {
return removeElement(o);
}Remove by index
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
int numMoved = elementCount - index - 1;
if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--elementCount] = null; // Let GC do its work
return oldValue;
}Set (set)
public synchronized E set(int index, E element) {
if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}Get (get)
public synchronized E get(int index) {
if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}Map – ConcurrentHashMap
ConcurrentHashMapis a drop‑in, thread‑safe replacement for HashMap. It uses internal segment locking to allow high concurrency without a global lock.
Add : put(K key, V value), putAll(Map<? extends K, ? extends V> m) Remove : remove(Object key), remove(Object key, Object value) Update : replace(K key, V value) Read : get(Object key), containsKey(Object key), containsValue(Object value) Atomic operations : putIfAbsent, compute, merge Key advantages: high performance with low contention, support for atomic compound operations, and scalable concurrent reads/writes compared with Hashtable or a synchronized HashMap.
Queue – Blocking Queues
LinkedBlockingQueue
Implements java.util.concurrent.BlockingQueue and is commonly used in producer‑consumer scenarios.
Add : add(E e), offer(E e), offer(E e, long timeout, TimeUnit unit), put(E e) (blocks when full)
Remove / Retrieve : remove(), poll(), poll(long timeout, TimeUnit unit), take() (blocks when empty),
peek()DelayQueue
DelayQueueis a blocking priority queue whose elements must implement java.util.concurrent.Delayed. An element becomes available only after its delay expires, making it suitable for scheduled tasks or log‑replay.
package org.funtester.performance.books.chapter02.section7;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
* Delay queue example
*/
public class DelayQueueDemo implements Delayed {
public static void main(String[] args) {
DelayQueue<DelayQueueDemo> delayQueue = new DelayQueue<>();
delayQueue.add(new DelayQueueDemo());
delayQueue.add(new DelayQueueDemo());
delayQueue.add(new DelayQueueDemo());
System.out.println(System.currentTimeMillis() + " 添加完成");
while (true) {
DelayQueueDemo demo = delayQueue.poll();
if (demo != null) {
System.out.println(System.currentTimeMillis() + " 取出成功");
}
}
}
/** Initialize delay of 3000 ms */
public DelayQueueDemo() {
this.timestamp = System.currentTimeMillis() + 3000;
}
/** Expiration timestamp (ms) */
long timestamp;
@Override
public long getDelay(TimeUnit unit) {
return this.timestamp - System.currentTimeMillis();
}
@Override
public int compareTo(Delayed o) {
return (int) (this.timestamp - ((DelayQueueDemo) o).timestamp);
}
}Running the demo prints a “添加完成” line, then after roughly three seconds prints three “取出成功” lines, confirming that elements are released only after their delay expires.
Other common blocking queues include SynchronousQueue (zero‑length), LinkedBlockingDeque (double‑ended), and PriorityBlockingQueue. All implement java.util.concurrent.BlockingQueue, so mastering one provides a basis for using the others.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
