优先使用java.util.concurrent包中的线程安全队列,如ArrayBlockingQueue、LinkedBlockingQueue和ConcurrentLinkedQueue,它们通过阻塞或CAS机制保证线程安全;若需手动控制,可采用synchronized或ReentrantLock对普通队列加锁,但需注意锁粒度与性能;即使队列本身线程安全,复合操作仍需额外同步以避免竞态条件。

在多线程环境下,确保队列操作的线程安全至关重要。Java 提供了多种方式来实现线程安全的队列操作,既能避免数据竞争,又能保证性能和正确性。
使用并发包中的线程安全队列
Java 的 java.util.concurrent 包提供了多个现成的线程安全队列实现,是最推荐的方式。
- BlockingQueue:支持阻塞插入和移除操作,适用于生产者-消费者模型。
- 常用实现类包括:
- ArrayBlockingQueue:基于数组的有界阻塞队列。
- LinkedBlockingQueue:基于链表的可选有界队列,吞吐量通常更高。
- PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
- ConcurrentLinkedQueue:非阻塞、无界的线程安全队列,基于 CAS 操作实现高性能。
示例:
BlockingQueuequeue.put("item"); // 阻塞直到有空间
String item = queue.take(); // 阻塞直到有元素
使用 synchronized 关键字保护普通队列
如果使用 ArrayList 或 LinkedList 等非线程安全集合,必须手动加锁。
立即学习“Java免费学习笔记(深入)”;
- 用 synchronized 修饰操作方法,或在代码块中同步对队列的访问。
- 需注意锁的粒度,避免影响性能。
示例:
private final Listpublic synchronized void add(String item) {
list.add(item);
}
public synchronized String remove() {
if (list.isEmpty()) return null;
return list.remove(0);
}
使用显式锁(ReentrantLock)增强控制
相比 synchronized,ReentrantLock 提供更灵活的锁定机制,比如尝试加锁、定时加锁等。
- 结合 Condition 可模拟阻塞行为。
- 适合需要精细控制锁逻辑的场景。
示例:
private final ReentrantLock lock = new ReentrantLock();private final Queue
public void add(String item) {
lock.lock();
try {
queue.add(item);
} finally {
lock.unlock();
}
}
基本上就这些。优先选择 java.util.concurrent 中的线程安全队列,它们经过充分测试且性能优秀。只有在特殊需求下才考虑手动加锁方式。不复杂但容易忽略的是:即使队列本身线程安全,复合操作(如检查后删除)仍可能需要额外同步。










