一.Map集合
map当中的key是不可重复的,value是可以重复的,从源码当中可以看出map当中的key是利用set组织起来的,所以利用keySet()可以获得key的set集合。
从图当中可以看出HashTable是基于Dictionary类,HashMap是基于AbstractMap类。
二.HashMap
1.hashCode
https://www.zhihu.com/question/20733617/answer/111577937 https://blog.csdn.net/justloveyou_/article/details/62893086
Key.hashcode 是 key 的自带的 hascode 函数是一个 int 值 32 位 数.
如果直接以散裂值hashcode作为下标去访问hashmap数组,考虑到二进制的int范围要40亿的映射空间,40亿长的数组内存是放不下的,扩容之前数组的默认大小才16,所以要对hashcode进行优化,调用扰动函数,将HashCode移动16位,再和原先的数据进行异或运算。
key的hashcode进过扰动函数hash(),以后,可以使key分布的更加均匀。
2.hashMap 参数以及扩容机制
[图片上传失败...(image-f041d5-1565428942742)]
3.get方法
4.put方法
也就是说数组中存储的是最后插入的元素。
5.HashMap 问题 jdk1.8 优化
6.将HashMap修改为线程安全的
要想实现线程安全,那么需要调用 collections 类的静态方法 synchronizeMap()实现 。
7.Hashmap 中的 key 可以为任意对象或数据类型吗?
三.HashTable
hashTable线程安全的实现:在对数组进行操作的时候,锁住整个table,效率低下。
无论是使用HashTable还是synchronized修饰的Hashmap当面对多线程并发的情况都要竞争同一把锁,导致效率十分低下,在java5以后,为了改进Hashtable的痛点引入了ConcurrentHashmap,
四. ConcurrentHashMap
ConconrentHashMap:对HashTable进行了优化,通过将锁细力化到每个table当中的元素,来提升并发性能,底层是通过数组+链表+红黑树实现的,ConcurrentHashMap的线程安全是通过CAS+synchronized来实现的,当插入数据的时候,会先通过hash判断该hash对应的数组元素是否为null,如果为null,则通过CAS进行插入,如果失败则继续循环尝试;如果不为null,则对链表或者红黑二叉树的头节点进行synchronized加锁,加锁以后在链表当中寻找,有就更新,没有就加载链表上。
对数组元素的跟新是通过CAS实现的
五.HashMap,Hashtable,ConcurrentHashMap的区别
Hashtable与ConcurrentHashMap的键和值都不可以为null,编译期报错
六.JUC
1.atomic
在Java5之前协调共享对象的访问时。只能采用synchronized和volatiole,在java5以后增加了locks,增加了显示锁,方便对共享资源做更细粒度上的控制
原子类:不可中断的操作,atomic包可以方便在多线程的情况下进行无锁的原子操作。atomic使用的是CAS(乐观锁,不加锁)的跟新方式,当某个线程在执行atomic方法的时候,不会被其他的线程锁打断,而别的线程就像是自旋锁一样,一直等到该方法执行完毕以后,才由JVM在等待队列当中选择一个线程来执行该atomic方法,他在软件层面上是非阻塞的,在底层借助了方法的原子属性。
2.tools多线程协调工具---并发工具类
这四个同步器的主要作用是协助线程的同步。
1.CountDownLatch同步计数器
如果我想让其他线程执行完指定程序,其他所有程序都执行结束后我再执行,这时可以用 CountDownLatch ,它是使用countDown()方法使count减1的,当前线程调用await()进行阻塞,每调用1次countDown()方法使count减1的,当count=0时,主线程执行,在此之前,调用countDown的线程是可以继续执行的。
2.CyclicBarrier
所有线程被阻塞在循环屏障处,每调用一次await(),count减1,当count=0时,一起执行
3.Semaphore
该类用于控制信号量的个数,构造时传入个数。程序执 行前用 acquire()方法获得信号,则可用信号减1,程序执行完通过 release()方法归还信号量,可用 信号加1.如果可用信号为 0,acquire 就会造成阻塞,等待 release 释放信号。acquire 和 release 方法可以不在同一个线程使用
4.Exchange
这个类用于交换数据,只能用于两个线程。当一个线程运行到 exchange()方法时会阻塞,另一 个线程运行到 exchange()时,二者交换数据,然后执行后面的程序。
3.Collection集合之BlockingQueue队列
如果队列满了,入队操作将阻塞,直到有空间可以使用,如果队列空了,出兑操作将阻塞,直到有元素可用。
1.ArrayBlockingQueue是基于数组实现的,他的长度有限(有边界),以先进先出的形式存储数据的,最先插入的数据在尾部,最先溢出的数据在头部。
2.LinkedBlockingQueue:也是采用先进先出的数据结构来存储数据的。