ArrayList和Vector的区别、如何实现线程安全

ArrayList和Vector都是单列集合
首先来说一下Java中集合和数组的区别:

  • 集合是可变长的容器,存在自动可扩容机制。数组是定长的,一旦满了,就不能继续添加了。
  • 集合只能存储引用类型的元素,而数组既可以存储引用类型的元素,也可以是基本数据类型的元素
  • 数组需要一段连续的空间来存储元素,但是一些非基于数组实现的集合是可以不需要连续的内存空间的

Vector和ArrayList的区别

两者都是单列、可变长集合,两者的底层都是基于数组实现的。

  • 初始化容量不同:如果使用无参构造来创建两者的实例的话,ArrayList的默认容量是0,Vector的默认初始容量是10
  • 扩容机制不同:ArrayList扩容后的容量是上一次的1.5倍,而Vector扩容后是上一次的2倍
  • 线程安全不同:ArrayList是线程不安全的,但是Vector所有的方法都使用了synchronized关键字修饰,是线程安全的
  • 效率不同:由于Vector的方法都使用了synchronized来修饰,所以效率低,ArrayList的效率高。

补充

实际中Vector用的比较少,因为效率问题。
如果在不考虑线程安全的情况下,是可以使用的ArrayList的,ArrayList的使用非常灵活。
常见的ArrayList的使用场景:

  • 封装数据库查询结果集
  • 集合操作,例如利用stream流对一组数据进行类型转换、过滤等处理时,可以封装到ArrayList中
  • 缓存,在一些需要缓存的场景下,可以使用ArrayList来存储数据,操作更高效。

解决

既然ArrayList是线程不安全的,而且Vector效率又很低,那么我在多线程环境下如何利用单列集合来存储数据呢?
可以利用Collections工具类中的synchronizedList()方法,将一个线程不安全的ArrayList转换成一个线程安全的集合。
这个线程安全的集合是Collections的一个静态内部类,这个静态内部类通过synchronized来实现线程安全,效率比synchronized锁一整个方法更高效一些。

// 创建一个普通的ArrayList
List<String> list = new ArrayList<>();
// 转换成一个线程安全的List
List<String> synList = Collections.synchronizedList(list);
// 接下来就可以对synList进行操作
// synList.add(xxx)
// synList.remove(xxxx)

Collections中还可以将线程不安全的LinkedList、Set、Map等实例,转换成线程安全的。

来看看Collections中的静态内部类,看几个经典方法

static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
//....
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
// ....
posted @   秋天Code  阅读(32)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示