vector线程安全但不推荐使用,因其单方法同步无法保证复合操作原子性,遍历时仍抛concurrentmodificationexception;安全遍历需用for循环配合get()或synchronized块。

Vector 是线程安全的,但不等于“推荐用”
Vector 的每个 public 方法(如 add()、get()、size())都加了 synchronized,所以单次操作是原子的。但这只意味着不会出现数据结构被并发破坏(比如数组越界、null pointer),不等于复合操作线程安全——比如“检查是否存在再添加”这种 if (!v.contains(x)) v.add(x); 依然会出错,因为两个方法之间存在竞态窗口。
常见误用场景:
- 用
Vector替代ArrayList以为“加了锁就万事大吉”,结果在遍历时仍抛ConcurrentModificationException(因为迭代器不是 fail-fast-safe 的) - 在高并发写入场景下性能暴跌,因为所有方法串行执行,吞吐量远低于
CopyOnWriteArrayList或ConcurrentHashMap
遍历 Vector 时怎么避免 ConcurrentModificationException
Vector 的 iterator() 和 listIterator() 仍是 fail-fast 的,和 ArrayList 一样:只要在迭代过程中有其他线程调用了结构性修改方法(如 add()、remove()),就会抛异常。
安全做法只有两种:
立即学习“Java免费学习笔记(深入)”;
- 用传统 for 循环配合
size()和get(i)—— 因为get()是同步的,且不依赖内部 modCount - 用
synchronized (vector) { ... }包裹整个遍历逻辑,确保期间无其他线程修改
示例:
Vector<String> v = new Vector<>();
// ✅ 安全:不依赖迭代器状态
for (int i = 0; i < v.size(); i++) {
String s = v.get(i);
System.out.println(s);
}
// ✅ 安全:显式同步块
synchronized (v) {
for (String s : v) { // 此时 for-each 等价于上面的同步遍历
System.out.println(s);
}
}
Vector 和 Collections.synchronizedList(ArrayList) 有什么区别
二者都提供同步包装,但实现层级不同:
-
Vector是类级别同步:每个实例方法自带synchronized,锁对象是this -
Collections.synchronizedList(new ArrayList())返回的是装饰器,所有方法代理到内部ArrayList,并在方法入口统一加synchronized (mutex),其中mutex默认是自身实例
关键差异:
- 锁对象可定制:
Collections.synchronizedList(list, myLock)允许传入自定义锁,便于多集合协同加锁;Vector锁死在实例上,无法外扩 - 迭代必须显式同步:两者都要求遍历时手动
synchronized,但Vector容易让人误以为“自带迭代安全” - Vector 是遗留类,自 Java 5 起官方文档已标注为“legacy”,不鼓励新代码使用
真正需要线程安全 List 时该选什么
除非你在维护 2000 年代初的老系统,否则别用 Vector。现代替代方案按场景分:
- 读多写少(如配置项列表)→
CopyOnWriteArrayList:迭代绝对安全,写操作复制底层数组,适合 size - 读写均衡、支持高频并发 →
ConcurrentLinkedQueue(若允许无序)或自己封装ConcurrentHashMap<integer e></integer>模拟索引访问(不推荐,复杂度高) - 需要强一致性 + 复合操作 → 改用
ReentrantLock+ArrayList手动控制临界区,比 Vector 更灵活可控
一个常被忽略的点:Vector 的 elementAt() 和 firstElement() 等老方法虽未废弃,但语义模糊(和 get()、get(0) 功能重复),混用容易引发理解偏差或 IDE 警告。










