Concurrent下的核心类
Executor:具有runnable任务的执行者
ExecutorService:一个线程池管理者,实现类有多种,能把runnable,callable提交到线程池中
Semaphore:一个计数信号量
ReentranLock:一个可重入的互斥锁定Lock,功能类似于synchronized锁,功能更强大写
Future: 表示异步计算的结果
BlockQueue:阻塞队列
CompletionService:ExecutorService的扩展类,可以获得线程的执行结果
CountDownLatch:一个同步辅助类,在完成一组正在其他线程执行的操作前,它允许一个或多个线程等待
CyclicBarrier:一个同步辅助类,它允许一组线程互相等待,直到达到某个公共屏障值。
Concurrent如何防止死锁
核心的接口:Lock和ReetranLock
JUC下几个常用的锁处理类:
ReentranLock:互斥锁
ReadWriteLock:读写锁
Condition:控制队列
LockSupport:阻塞原语
Semaphore:信号量
CountDownLatch:闭锁
CyclicBarrier:栅栏
Exchange:交换机
CompletableFuture:线程回调
由于synchronized可以保证数据安全,但是所有的线程只能共享一把锁,所以JUC中做了各类工具的引用
重新认识ConcurrentHashMap和CopyOnWriteArrayList
ConcurrentHashMap
ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。
Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。
一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。
CopyOnWriteArrayList
这是一个ArrayList的线程安全的变体,其原理大概可以通俗的理解为:初始化的时候只有一个容器,很常一段时间,这个容器数据、数量等没有发生变化的时候,大家(多个线程),都是读取(假设这段时间里只发生读取的操作)同一个容器中的数据,所以这样大家读到的数据都是唯一、一致、安全的.
但是后来有人往里面增加了一个数据,这个时候CopyOnWriteArrayList 底层实现添加的原理:
先通过lock.lock获取到锁,保证一次只有一个线程添加元素
然后copy出一个容器(可以简称副本),这个副本的长度为原数组的length+1
再往新的容器里添加这个新的数据,最后把新的容器的引用地址赋值给了之前那个旧的的容器地址
CopyOnWriteArrayList最大的问题是不能保证数据的实时一致性,因为若是有线程在进行写操作的时候,其他读操作的线程仍是读老的list,不能保证立马看到数据的改变