🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
并发集合常见的有ConCurrentHashMap,ConcurrentllinkedQueue,ConcurrentLinkedDeque等,并发集合位于Java.util.concurrent包下,是JDK5之后有的。 在Java中有普通集合,同步(线程安全)的集合,并发集合,普通集合通常性能最高,但是不保证多线程的安全行和并发的可靠性,线程安全集合仅仅是给集合添加了synchronize同步锁,严重牺牲了性能,而且对并发的效率就更低了,并发集合则通过复杂的策略不仅保证了多线程的安全又提高了并发时的效率。 ## **ConcurrentHashMap** ConcurrentHashMap是线程安全的HashMap实现,默认构造同样有initalCapacity和loadFactor属性,不过还多了一个concurrencyLevel属性,三属性的默认值分别是16、0.75及16。其内部使用锁分段技术,维持这锁Segment的数组,在Segment数组中又存放着Entity[]数组,内部hash算法将数据较均匀分部在不同锁中。 **put方法** 在ConcurrentHashMap中并没有给put方法加上synchronize,首先是对key.hashcode进行hash操作,得到key的hash值。hash操作的算法和map也不同,根据此hash值计算并获取到其对应数组内的segment对象,在根据segme对象调用put方法来完成操作。 <br/> concurrentHashMap基于concurrencylevel划分出了多个Segme来对key-value进行存储,从而避免每次put操作都要锁住整个数组,在默认情况下,最佳的情况可允许16个线程并发无阻塞的操作集合对象,尽可能的减少并发时造成的阻塞情况<br/> **get** 同样也没在方法上加synchronize,首先对key.hashcode进行Hash操作,基于其值找到对应的Segment对象,调用get方法完成当前操作,而Segment的get方法首先通过hash值和对象数组大小减1的值进行按位与操作来获取数组上对应位置的HashEntity。在这个步奏中,可能会因为对象数组大小的改变,以及数组上对应位置的HashEntity产生不一致性,那么ConcurrentHashMap是如何实现的: 对象数组大小的改变只有在put操作时有可能发生,由于HashEntity对象数组对应的变量是volatile类型的,因此可以保证如HashEntity对象数组大小发生改变,读操作可看到最新的对象数组大小。 在读取到了HashEntity对象后,怎么能保证它及其next属性构成链表上的对象不会改变呢?