读操作性能
Vector
:读操作时需要获取锁,这会导致在多线程环境下,如果有其他线程正在进行写操作,读操作会被阻塞,性能相对较低。因为锁的存在限制了并发读的能力。
Collections.synchronizedList
:与Vector
类似,读操作也需要获取锁。当有多个线程同时读取时,同样会因为锁竞争而降低性能,在高并发读场景下表现不佳。
CopyOnWriteArrayList
:读操作不需要加锁。因为它是基于数组的复制,读操作直接读取原数组,不会影响写操作,所以读操作性能非常高,特别适合读多写少的场景。
写操作性能
Vector
:写操作(如add
、remove
等)需要获取锁,在多线程环境下,锁的竞争会导致写操作的性能瓶颈。如果有大量的写操作,线程等待锁的时间会增加,整体性能下降。
Collections.synchronizedList
:同Vector
,写操作加锁,多线程下锁竞争会影响性能,大量写操作时效率较低。
CopyOnWriteArrayList
:写操作(如add
、remove
)时会复制一份新的数组,然后在新数组上进行操作,最后将原数组引用指向新数组。由于复制数组的开销较大,写操作性能相对较低,尤其是在数据量较大时。
应用场景
Vector
:适用于早期Java版本(JDK 1.0就存在),对线程安全集合需求简单,并且读写操作频率相对均衡的场景。不过由于其性能问题,现在较少使用。
Collections.synchronizedList
:适用于对已有List
进行快速线程安全包装的场景,当读写操作频率较为均衡且并发量不是特别高时可以使用。例如,在一些遗留代码改造中,需要快速将普通List
变为线程安全的场景。
CopyOnWriteArrayList
:适用于读多写少的场景,比如系统配置信息的存储、日志记录等。例如,一个应用程序需要频繁读取配置信息,但很少修改配置,就可以使用CopyOnWriteArrayList
来存储配置项。
示例代码
Vector
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
Vector<Integer> vector = new Vector<>();
vector.add(1);
vector.add(2);
// 读操作
int value = vector.get(0);
// 写操作
vector.add(3);
}
}
Collections.synchronizedList
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SynchronizedListExample {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
List<Integer> synchronizedList = Collections.synchronizedList(list);
synchronizedList.add(1);
synchronizedList.add(2);
// 读操作
int value = synchronizedList.get(0);
// 写操作
synchronizedList.add(3);
}
}
CopyOnWriteArrayList
import java.util.concurrent.CopyOnWriteArrayList;
public class CopyOnWriteArrayListExample {
public static void main(String[] args) {
CopyOnWriteArrayList<Integer> cowList = new CopyOnWriteArrayList<>();
cowList.add(1);
cowList.add(2);
// 读操作
int value = cowList.get(0);
// 写操作
cowList.add(3);
}
}