这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
引言
最近在学习群里看到群友们在讨论一个问题:并发的向ArrayList里添加10000个元素元素,最后打印出ArrayList的size(),打印结果小于10000,便在群里问这事怎么回事?
首先我们针对三个小伙伴的代码挨个来点评下:
代码检视
第一位
首先,这个小伙伴饭了一个非常恐怖的错误, for循环里面创建了一万个线程,这对程序来说无疑是一个灾难。虽然这里是一个单机的Demo程序,对于资深的程序员来说,有些东西是要刻在DNA里面的。虽然Java程序员不能像C++程序员对每一块内存都如数家珍,但也不能这么暴殄天物。
其次,这位同学不知道在哪里学到的这个等待线程全部执行完成的方法,while(Thread.activeCount() > 2)很神奇,他还解释说,如果是IDEA这里写2,如果用Eclipse这里写1。说实话还有点可爱。(说明:此方法仅能在运行单机Demo时测试用,在生产环境实不可取的。)好的地方是他考虑到了主线程会早于new出来的线程结束,所以让CPU空转来等待其他线程完成。
说完了编码上的硬伤,我们来看一下这位同学对并发安全的理解:没有理解。他完全没有做任何线程安全的措施,所以输出的结果 9990 是不符合预期的,好吧,我们来看下一位。
第二位
在得到其他童鞋的指点后,第二位同学马上做出了调整
第二位的第二次尝试
第二位同学放弃了。
ArrayList的线程安全性
大家都知道ArrayList不是线程安全的,那他究竟是怎么不安全了。如何让他变得安全,今天我们就来看看。
啪,很快啊,我就写出了一串代码
1 | java复制代码import java.util.ArrayList; |
简单说下思路:
// todo
创建一个线程池,然后使用
执行结果:
不安全的版本
用时:4370 ms
result: 9984520
安全的版本 - 使用synchronize
用时:3410 ms
result: 10000000
安全的版本 - 使用ReentrantLock
用时:6688 ms
result: 10000000
安全的版本 - 使用Collections.synchronizedList(new ArrayList<>())
用时:3033 ms
result: 10000000
Process finished with exit code 0
本文转载自: 掘金