2019-08-09 Java的JUC包

一.Map集合

map当中的key是不可重复的,value是可以重复的,从源码当中可以看出map当中的key是利用set组织起来的,所以利用keySet()可以获得key的set集合。


集合体系
从图当中可以看出HashTable是基于Dictionary类,HashMap是基于AbstractMap类。
image.png

二.HashMap

image.png

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分布的更加均匀。
image.png

2.hashMap 参数以及扩容机制

image.png

[图片上传失败...(image-f041d5-1565428942742)]

3.get方法

image.png

4.put方法

image.png

也就是说数组中存储的是最后插入的元素。

5.HashMap 问题 jdk1.8 优化

image.png

6.将HashMap修改为线程安全的

要想实现线程安全,那么需要调用 collections 类的静态方法 synchronizeMap()实现 。


image.png

7.Hashmap 中的 key 可以为任意对象或数据类型吗?

image.png

三.HashTable

hashTable线程安全的实现:在对数组进行操作的时候,锁住整个table,效率低下。
无论是使用HashTable还是synchronized修饰的Hashmap当面对多线程并发的情况都要竞争同一把锁,导致效率十分低下,在java5以后,为了改进Hashtable的痛点引入了ConcurrentHashmap,


四. ConcurrentHashMap

image.png

image.png

ConconrentHashMap:对HashTable进行了优化,通过将锁细力化到每个table当中的元素,来提升并发性能,底层是通过数组+链表+红黑树实现的,ConcurrentHashMap的线程安全是通过CAS+synchronized来实现的,当插入数据的时候,会先通过hash判断该hash对应的数组元素是否为null,如果为null,则通过CAS进行插入,如果失败则继续循环尝试;如果不为null,则对链表或者红黑二叉树的头节点进行synchronized加锁,加锁以后在链表当中寻找,有就更新,没有就加载链表上。

对数组元素的跟新是通过CAS实现的

五.HashMap,Hashtable,ConcurrentHashMap的区别

image.png

Hashtable与ConcurrentHashMap的键和值都不可以为null,编译期报错

六.JUC

1.atomic

image.png

image.png
在Java5之前协调共享对象的访问时。只能采用synchronized和volatiole,在java5以后增加了locks,增加了显示锁,方便对共享资源做更细粒度上的控制

原子类:不可中断的操作,atomic包可以方便在多线程的情况下进行无锁的原子操作。atomic使用的是CAS(乐观锁,不加锁)的跟新方式,当某个线程在执行atomic方法的时候,不会被其他的线程锁打断,而别的线程就像是自旋锁一样,一直等到该方法执行完毕以后,才由JVM在等待队列当中选择一个线程来执行该atomic方法,他在软件层面上是非阻塞的,在底层借助了方法的原子属性。

2.tools多线程协调工具---并发工具类

image.png

这四个同步器的主要作用是协助线程的同步。

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()时,二者交换数据,然后执行后面的程序。


image.png

3.Collection集合之BlockingQueue队列

image.png

如果队列满了,入队操作将阻塞,直到有空间可以使用,如果队列空了,出兑操作将阻塞,直到有元素可用。


1.ArrayBlockingQueue是基于数组实现的,他的长度有限(有边界),以先进先出的形式存储数据的,最先插入的数据在尾部,最先溢出的数据在头部。
2.LinkedBlockingQueue:也是采用先进先出的数据结构来存储数据的。

你可能感兴趣的:(2019-08-09 Java的JUC包)