Java|面试官:请说一下Java同步容器


Java|面试官:请说一下Java同步容器
文章图片
Java|面试官:请说一下Java同步容器
文章图片
Java|面试官:请说一下Java同步容器
文章图片
Java|面试官:请说一下Java同步容器
文章图片

为了方便编写出线程安全的程序 , Java里面提供了一些线程安全类和并发工具 , 比如:同步容器、并发容器、阻塞队列、Synchronizer(比如CountDownLatch) 。 今天我们就来讨论下同步容器 。
1、为什么会出现同步容器?在Java的集合容器框架中 , 主要有四大类别:List、Set、Queue、Map 。
List、Set、Queue接口分别继承了Collection接口 , Map本身是一个接口 。
【Java|面试官:请说一下Java同步容器】注意Collection和Map是一个顶层接口 , 而List、Set、Queue则继承了Collection接口 , 分别代表数组、集合和队列这三大类容器 。
像ArrayList、LinkedList都是实现了List接口 , HashSet实现了Set接口 , 而Deque(双向队列 , 允许在队首、队尾进行入队和出队操作)继承了Queue接口 , PriorityQueue实现了Queue接口 。 另外LinkedList(实际上是双向链表)实现了Deque接口 。
像ArrayList、LinkedList、HashMap这些容器都是非线程安全的 。
如果有多个线程并发地访问这些容器时 , 就会出现问题 。
因此 , 在编写程序时 , 必须要求程序员手动地在任何访问到这些容器的地方进行同步处理 , 这样导致在使用这些容器的时候非常地不方便 。
所以 , Java提供了同步容器供用户使用 。
2、Java中的同步容器类在Java中 , 同步容器主要包括2类:
1)Vector、Stack、HashTable
2)Collections类中提供的静态工厂方法创建的类
Vector实现了List接口 , Vector实际上就是一个数组 , 和ArrayList类似 , 但是Vector中的方法都是synchronized方法 , 即进行了同步措施 。
Stack也是一个同步容器 , 它的方法也用synchronized进行了同步 , 它实际上是继承于Vector类 。
HashTable实现了Map接口 , 它和HashMap很相似 , 但是HashTable进行了同步处理 , 而HashMap没有 。
Collections类是一个工具提供类 , 注意 , 它和Collection不同 , Collection是一个顶层的接口 。 在Collections类中提供了大量的方法 , 比如对集合或者容器进行排序、查找等操作 。 最重要的是 , 在它里面提供了几个静态工厂方法来创建同步容器类 , 如下图所示:
3、同步容器的缺陷从同步容器的具体实现源码可知 , 同步容器中的方法采用了synchronized进行了同步 , 那么很显然 , 这必然会影响到执行性能 , 另外 , 同步容器就一定是真正地完全线程安全吗?不一定 , 这个在下面会讲到 。
我们首先来看一下传统的非同步容器和同步容器的性能差异 , 我们以ArrayList和Vector为例:
1)性能问题
我们先通过一个例子看一下Vector和ArrayList在获取数据时性能上的差异:
输出结果:
可以看出Vector的get操作比ArrayList耗时要多 。 这只是其中的一方面性能问题上的反映 。
由于Vector中的add方法和get方法都进行了同步 , 因此 , 在有多个线程进行访问时 , 如果多个线程都只是进行读取操作 , 那么每个时刻就只能有一个线程进行读取 , 其他线程便只能等待 , 这些线程必须竞争同一把锁 。


推荐阅读