本章主要介绍了并发容器(ConcurrentHashMap、ConcurrentLinkedQueue、阻塞队列)和并发框架(Fork/Join框架),并分析了其内部原理。
ConcurrentHashMap的实现原理与使用
ConcurrentHashMap是线程安全且高效的HashMap。
为什么要使用ConcurrentHashMap
- 线程不安全的HashMap
- 效率低下的HashTable
- ConcurrentHashMap的锁分段技术可有效提升并发访问率
ConcurrentHashMap的结构
ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁(ReentrantLock),在ConcurrentHashMap里扮演锁的角色;HashEntry则用于存储键值对数据。
核心操作:
- get操作
- put操作
- 是否需要扩容
- 如何扩容
- size操作
ConcurrentHashMap的类图:
ConcurrentHashMap的结构图:
ConcurrentLinkedQueue
非阻塞的方式来实现线程安全队列。
ConcurrentLinkedQueue的结构
ConcurrentLinkedQueue的类图:
入队列
入队列就是将入队节点添加到队列的尾部。
1 | public boolean offer(E e) { |
出队列
出队列的就是从队列里返回一个节点元素,并清空该节点对元素的引用。
1 | public E poll() { |
Java中的阻塞队列
本节将介绍什么是阻塞队列,以及Java中阻塞队列的4种处理方式,并介绍Java 7中提供的7种阻塞队列,最后分析阻塞队列的一种实现方式。
什么是阻塞队列
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。
阻塞队列的4种处理方式:
Java里的阻塞队列
JDK 7提供了7个阻塞队列,如下:
- ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
- LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
- PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
- DelayQueue:一个使用优先级队列实现的无界阻塞队列。
- SynchronousQueue:一个不存储元素的阻塞队列。
- LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
- LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
ArrayBlockingQueue
ArrayBlockingQueue是一个用数组实现的有界阻塞队列。
1 | ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true); |
…..
阻塞队列的实现原理
使用通知模式实现。底层是Condition来实现。
1 | private final Condition notFull; |
Fork/Join框架
本节将会介绍Fork/Join框架的基本原理、算法、设计方式、应用与实现等。
什么是Fork/Join框架
Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干
个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
流程图:
使用Fork/Join框架
让我们通过一个简单的需求来使用Fork/Join框架,需求是:计算1+2+3+4的结果。
1 | import java.util.concurrent.ExecutionException; |
Fork/Join框架的异常处理
ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常。getException方法返回Throwable对象,如果任务被取消了则返回CancellationException。如果任务没有完成或者没有抛出异常则返回null。使用如下代码:
1 | if(task.isCompletedAbnormally()) |