java集合几个知识点

1.arraylist在默认容量是10,每次进行add的时候会检查容量,如果需要扩容则增加1.5倍,如果仍然小,则设为增加后的长度大小


2.copyonwritearraylist 保证线程安全的方法是:不对读进行限制,写的操作加重入锁,写的时候拷贝一份数组,并将新数据写入,完成后再将引用返回。

                                 重新设置引用是一个原子操作。适用于写的操作比较少,重点为读操作的并发情况。 在迭代的时候,由于写操作不会更改当前迭代器的容器引用,因此不                                   会有concurrent异常。


3. collections.synchronizedlist : 对每个方法(迭代器除外)加了对象锁。所以在进行单次调用list方法的时候保证线程安全。但是可能会存在竞态条件。所以客户端进行

                       使用的时候要注意加外部锁。一个典型的例子是,自动以一个方法,需要先调用list的读方法,再改写list,虽然两个方法都是线程安全的,但是在两个方法调用                           期间可能会有其他线程对list进行修改,这会导致迭代器最终抛出异常。此时需要在客户端方法上添加synchronize(list)进行外部加锁,这样可以保证两个操作                          之间不会有其他线程修改list(方法的对象锁不能使自定义的类,这样没有办法阻止其他线程访问list)   此竞态条件也会出现在其他并发容器中,包括上面那一条

                      相比于copyonwritearraylist,写的效率明显更高,读的效率略微下降

                       容器3的迭代器是不安全的!


4.HashMap   http://blog.csdn.net/jzhf2012/article/details/8540670

                      默认大小是16,且容量必须是2的次幂,有最大值为2的30次幂。默认因子为0.75,为扩容的临界系数。 

                    底层数据结构为一个数组,每个元素存一个链表,链表元素为Entry<K,V>。 定位元素的过程是: 1.通过key的hashcode值来计算出一个新的hash值(防止原来的                         hashcode写的不好),通过新的hash和底层数组table的长度来定位index

                    2.通过index找到数组中的第一个Entry元素. 循环链表查找是否有key与当前元素相同。  判断相同的方法为:先判断hash值是否相同,在判断equals和==。

                      所以自定义类的时候,如果要用到map,切记重写hashcode和equals方法

                   HashMap为什么是线程不安全的:当添加或删除的时候,如果操作的key的hash值一样,会导致多个线程对同一个链表进行操作(结构改变),这会导致后一个线                     程的操作覆盖前一个线程(1.同时在链表上添加entry 2.同时删除enry 3.重新分配哈希表,数组结构更新)


5.LinkedHashMap :可以预知排序顺序,两种:插入时的顺序,或者是访问的顺序
                               Entry的数据结构比Hashmap中的Entry多了两个变量,before和after,以此来建立Entry的链表

                               实际上就是一个Hashmap+Linklist  

                               在底层数据结构中增加了一个双向链表来储存Entry引用,设立一个boolean的标志位,来决定是已插入顺序储存还是最近访问顺序储存

                              若以访问顺序储存,则每次操作一个节点后,调整链表顺序。


6.TreeMap: http://blog.csdn.net/chenssy/article/details/26668941


7.concurrentskiplistmap:http://blog.csdn.net/sunxianghuang/article/details/52221913

    对高并发有较好的支持,底层实现是利用跳表的数据结构。Entry是排序的。查找等操作的时间复杂度是log(n)。

   利用CAS方法保证线程安全





容器的三种安全并发方式比较

1.CopyOnWrite

写操作加锁,并在一个副本上进行写操作,同时读操作不加锁,读的时候读的是原始容器。写操作执行的最后一步是给引用赋值最新的副本容器,这是一个原始操作。

由于集成体系不同,他没有modelcount变量,因此不会抛出快速失败异常

性能上,写操作性能差,读操作性能高

2.Collections.synchronized 

对非安全容器内部方法加锁,迭代器不加锁。所以,在用容器内部迭代器时,另一个线程的写操作会导致迭代快速失败。

写性能高于copyonwrite,读性能略低于前者  

注:1和2继承的体系完全不同,前者继承了abstractlist骨架类,后者实现了randomaccess接口

3.Concurrent(HashMap)  http://www.cnblogs.com/ITtangtang/p/3948786.html

采用了分段锁,将一个table分成了若干segment,每个segment有自己的锁,所以可以并发访问不同的segment。

数据结构(以map为例):一个HashEntry节点中的key,next和hash都是final的,value是 volatile的,所以读操作不需要加锁

由于next是final的,所以remove必须先clone删除点之前所有的节点,然后将最后一个节点的next指向删除点后一个节点

插入必须在头部插入

并发效率高,但若一致性。不会快速失败,迭代实际上是迭代底层的数组,已经迭代过的值改变不影响,未迭代的值变化则会体现在接下来的读取中


高并发的时候尽量使用2和3,具体选择根据读写情况决定


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值