CopyOnWriteArrayList和SynchronizedList这两者循环插入数据时,执行效率都有不利的地方,CopyOnWriteArrayList是每次都要弄个快照,添加完,把快照数据给主数据,再废掉快照,SynchronizedList则是到处加锁,加锁,就需要解锁。
今天闲来无事,自己写个demo来做测试,循环加一百万个数字。JDK版本1.8。
Instant begin = Instant.now();
long beginLong = begin.toEpochMilli();
Collections.synchronizedList(new ArrayList<>(1048576));
for(int i= 0; i<1_000_000; i++) {
list.add(i);
}
Instant end = Instant.now();
long endLong = end.toEpochMilli();
System.out.println((endLong - beginLong));
使用SynchronizedList,执行时间:54ms
再用CopyOnWriteArrayList试试看
Instant begin = Instant.now();
long beginLong = begin.toEpochMilli();
List<Integer> list = new CopyOnWriteArrayList<>(new ArrayList<>(1048576));
for(int i= 0; i<1_000_000; i++) {
list.add(i);
}
Instant end = Instant.now();
long endLong = end.toEpochMilli();
System.out.println((endLong - beginLong));
执行时间:598375ms,接近10分钟了。差距将近1000倍。
再用CopyOnWriteArrayList的addAll试试看
Instant begin = Instant.now();
long beginLong = begin.toEpochMilli();
List<Integer> list = Collections.synchronizedList(new ArrayList<>(1048576));
for(int i= 0; i<1_000_000; i++) {
list.add(i);
}
Instant end = Instant.now();
long endLong = end.toEpochMilli();
List<Integer> abcd = new CopyOnWriteArrayList<>();
abcd.addAll(list);
Instant end1 = Instant.now();
long endLong1 = end1.toEpochMilli();
System.out.println((endLong - beginLong));
System.out.println((endLong1 - endLong));
执行结果:3ms。
List<Integer> abcd = new CopyOnWriteArrayList<>(list);
直接将一个List作为初始化时的参数的执行时间也差不多是2ms-3ms。
所以,如果要循环插入大量信息,SynchronizedList的效率较高,CopyOnWriteArrayList基本可以放弃。但如果前面已经有获得的List数据,以addAll的方式或者使用构造方法一次性批量加入CopyOnWriteArrayList,这个效率还是很高的。