vector和stack是jdk 1.0遗留的线程安全集合,vector为加synchronized锁的动态数组,stack继承vector并提供栈操作,但二者锁粒度粗、性能差,已不推荐用于新项目,应优先选用arraydeque、copyonwritearraylist等现代替代方案。

Java 中 Vector 和 Stack 是 JDK 1.0 就存在的线程安全集合,适合简单场景下快速获得同步能力,但它们不是现代高并发首选方案——用法简单,代价明确。
Vector:带锁的动态数组
Vector 是 List 接口的早期实现,所有 public 方法(add、get、remove、size 等)都加了 synchronized,保证单个操作原子性。
- 构造方式灵活:可指定初始容量(如
new Vector(16))或扩容增量(new Vector(10, 5),每次扩容加 5 而非翻倍) - 支持 null 元素,保持插入顺序,允许重复
- 性能瓶颈明显:读写都锁整个对象,多线程频繁读时也互相阻塞
- 不推荐用于新项目;若必须用,避免在循环中反复调用
size()或get(i),可先缓存 size 值减少同步开销
Stack:基于 Vector 的线程安全栈
Stack 继承自 Vector,因此天然具备线程安全性。它只暴露栈语义方法(push/pop/peek/search),但底层仍是数组,且所有栈方法也都加了 synchronized。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 典型用法:
Stack<string> stack = new Stack(); stack.push("a"); String top = stack.pop();</string> - 注意:虽然继承 Vector,但不要混用 Vector 特有方法(如
elementAt()、insertElementAt()),否则破坏 LIFO 原则 - search() 返回从栈顶开始的位置(1-indexed),不是索引值;空栈返回 -1
- 实际开发中更推荐用
Deque实现(如ArrayDeque),它更快、更规范,且 Stack 已被官方标记为“遗留类”
使用时的关键提醒
Vector 和 Stack 的线程安全仅限于单个方法调用,组合操作仍需手动同步。
- 例如判断非空再 pop:
if (!stack.isEmpty()) stack.pop();不是原子操作,可能抛出 EmptyStackException - 遍历 Vector 或 Stack 时,不能直接用 for-each 或 Iterator,否则可能触发 ConcurrentModificationException;必须用传统 for 循环 + get(i),或在外层 synchronized 块中迭代
- 若需更高吞吐量的线程安全 List,优先考虑
Collections.synchronizedList(new ArrayList())(稍好于 Vector)或CopyOnWriteArrayList(适用于读多写少) - 对于栈结构,
ArrayDeque配合push()/pop()方法,性能更好,且无历史包袱
替代建议:为什么现在少用它们
Vector 和 Stack 的设计目标是“让老代码跑起来”,而非“高效并发”。它们的锁粒度粗、API 冗余(如 Vector 的 addElement 与 add 功能重复)、缺乏现代集合的扩展能力(如 Stream 支持)。
- Vector → 替代方案:
CopyOnWriteArrayList(读多写少)、ConcurrentLinkedQueue(队列场景)、或显式加锁 + ArrayList - Stack → 替代方案:
ArrayDeque(推荐作为栈使用)、ConcurrentLinkedDeque(高并发栈) - 真正需要强一致性+复杂操作时,应结合 ReentrantLock 或读写锁自行控制临界区,而不是依赖重量级同步容器
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










