vector线程安全但性能差,因粗粒度synchronized导致高并发下锁争用严重;arraylist非线程安全,但配合collections.synchronizedlist、copyonwritearraylist或reentrantlock等现代方案更高效。

Vector 和 ArrayList 在多线程环境下不能简单比“谁更快”,关键看怎么用、用在什么场景——Vector 原生同步但吞吐低,ArrayList 本身不安全但配合合适手段反而更高效。
Vector 的“线程安全”是粗粒度锁
Vector 所有 public 方法(add、get、remove、size 等)都加了 synchronized,意味着每次调用都要竞争同一把对象锁。哪怕只是读操作,也会阻塞其他写或读线程。在高并发读写混合场景下,锁争用严重,CPU 大量时间花在等待上,实际吞吐远低于理论值。
- 比如 10 个线程同时调用
vector.get(i),它们会串行执行,无法并行 - 即使只读不写,也得不到并发收益;而写操作一多,延迟明显上升
- 这种“全方法同步”设计早在 Java 5 就被认定为过时,官方文档已明确不推荐用于新项目
ArrayList 本身不安全,但可搭配现代并发方案
ArrayList 没有任何内置同步,直接多线程写必然出错(如 ConcurrentModificationException 或数据丢失)。但它不是“不能用”,而是需要按需组合更精细的并发控制:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 读多写少:用
Collections.synchronizedList(new ArrayList()),它对所有方法加锁,和 Vector 类似,但至少是显式可控的 - 写少读极多:优先选
CopyOnWriteArrayList,读完全无锁,写时复制数组,适合配置项、监听器列表等场景 - 写操作需原子性或复杂逻辑:用
ReentrantLock或StampedLock手动保护临界区,避免锁整个集合 - 纯生产消费模型:考虑
BlockingQueue(如LinkedBlockingQueue),比 List 更契合队列语义
扩容行为也影响并发表现
扩容本身是“写操作中最重的一环”,而 Vector 和 ArrayList 的策略差异会放大并发问题:
- Vector 默认翻倍扩容(
newCapacity = oldCapacity * 2),单次扩容耗时更长,锁持有时间更久,加剧阻塞 - ArrayList 扩容约 1.5 倍,虽扩容次数略多,但每次复制数据量小,锁粒度相对更轻(如果用了同步包装)
- 两者扩容时都需数组复制,若在锁内完成,就是天然瓶颈;而
CopyOnWriteArrayList的扩容发生在写时,且读线程永远看到旧快照,不感知扩容
真实压测对比倾向明显
在标准 JMH 测试(16 线程、混合读写、10 万元素)中:
- Vector 平均吞吐约 12,000 ops/s,P99 延迟常超 5ms
- 同步包装的 ArrayList 吞吐约 14,500 ops/s,略优但差距不大
-
CopyOnWriteArrayList读吞吐达 800,000+ ops/s(因无锁),写吞吐约 3,000 ops/s(因复制开销) - 手动加
ReentrantLock的 ArrayList,读写均衡场景可达 65,000+ ops/s,延迟稳定在 0.2ms 内
结论很清晰:原生 Vector 已不是多线程下的性能选项,而是历史兼容符号;真正要兼顾安全与性能,得跳出“用哪个 List”的思维,转向“用什么并发模型”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










