Fundamentals 12 min read

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.

FunTester
FunTester
FunTester
Mastering Thread‑Safe Java Collections: Vector, ConcurrentHashMap, and Blocking Queues

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

Vector

implements 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

ConcurrentHashMap

is 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

DelayQueue

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

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconcurrencyCollectionsConcurrentHashMapVectorthread-safeBlockingQueue
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.