我的探险生涯手游单机版
63.16MB · 2025-11-27
原文来自于:zha-ge.cn/java/80
先来个场景,某次面试,我原本信心满满,BAT大厂二面官,眉头一扬直接来了句:“那你说说 CopyOnWriteArrayList 吧。”瞬间脑子嗡了一下,这玩意儿不是数组那一挂的么,居然还能成为拷问灵魂的问题!好了,今天就来随意聊聊 CopyOnWriteArrayList。如果你也遇到过类似问题,不妨听听我的“踩坑日记”。
其实这个名字,光看 CopyOnWrite 就挺直白了,写的时候才复制。听起来有点像小时候考试,平时作业抄的安心,真遇到老师收本子,才瑟瑟发抖赶紧抄标准答案……
为啥会用它?两个字:线程安全。 还是有人疑惑,这么多集合,为啥就它特别?
顺嘴提一句,CopyOnWriteArrayList 最适合“读多写少”的场景。 比如系统有个配置表,万年不改,偏偏读的人特别多,就它香。
我当初第一次用 CopyOnWriteArrayList,想着线程安全,放心大胆往里怼。哪知道,下面这场面直接把我气笑。
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("蛋炒饭");
list.add("牛奶");
// 每次 add/remove,其实都复制一遍数组
list.remove("蛋炒饭"); // 这一步悄咪咪复制了一份新数组
// ……
问题来了,写操作多起来,内存就猛涨。本来想着省事,没想到一大堆写入,一晚上 jvm 都快被吃挂了。
最迷惑的时候是遍历。 你以为会像普通 ArrayList 那样:
for (String dish : list) {
// 假装有写操作
list.remove(dish);
}
结果 CopyOnWriteArrayList 压根不甩你,遍历期间的写操作,压根不报错,也不会“瞬时生效”,遍历用的是遍历前的旧快照,活脱脱“井水不犯河水”,你删除你自己的,遍历我还是老样子,完全看不到你的骚操作。 这跟 ArrayList 那动不动就 ConcurrentModificationException 的暴脾气完全不一样。
让我总结一下血泪教训:
CopyOnWriteArrayList 这个家伙吧,本质上就像写日记:写的时候影印一份,谁爱怎么改怎么改,看的时候一律享受历史快照,不用担心中间被捣乱。优点爽快,缺点明显,得看清场景再下手。
最后,面试如果遇到,别慌,就聊聊它的底层原理+适用场景+注意点,分分钟给面试官来个灵魂三连(其实我后来就这么糊弄过的,效果还挺好)。 大家伙有啥踩坑经历,也欢迎留言吐槽,我们互相取暖~
——溜了,今晚先不写代码,吃点蛋炒饭压压惊。