第5章 基础构建模块
文章目录
5.1 同步容器类
5.1.1 同步容器类的问题
5.1.2 迭代器与ConcurrentModificationException
5.1.3 隐藏迭代器
5.2 并发容器
5.2.1 ConcurrentHashMap
只有当应用程序需要加锁Map以进行独占访问时,才应该放弃使用ConcurrentHashMap
5.2.2 额外的原子Map操作
5.2.3 CopyOnWriteArrayList
仅当迭代操作远远多于修改操作时,才应该使用“写入时复制”容器
5.3 阻塞队列和生产者-消费者模式
BlockingQueue
- LinkedBlockingQueue和ArrayBlocking-Queue是FIFO队列,二者分别与LinkedList和ArrayList类似,但比同步List拥有更好的并发性能
- PriorityBlockingQueue是一个按优先级排序的队列,当你希望按照某种顺序而不是FIFO来处理元素时,这个队列将非常有用
- SynchronousQueue实际上不是一个真正的队列,因为它不会为队列中元素维护存储空间。与其他队列不同的是,它维护一组线程,这些线程在等待着把元素加入或移出队列。仅当有足够多的消费者,并且总是有一个消费者准备好获取交付的工作时,才适合使用同步队列
5.3.2 串行线程封闭
线程封闭对象只能由单个线程拥有,但可以通过安全地发布该对象来转移所有权。阻塞队列、ConcurrentMap#remove、AtomicReference#compareAndSet
5.3.3 双端队列与工作密取(Work Stealing)
Deque:队头队尾插入移除
- ArrayDeque
- BlockingDeque
- LinkedBlockingDeque
工作密取:每个消费者都有各自的双端队列,如果它完成了自己双端队列中的全部工作,那么它可以从其他消费者双端队列末尾秘密地获取工作。适用于既是消费者也是生产者问题
5.4 阻塞方法与中断方法
5.5 同步工具类
5.5.1 闭锁
延迟进程的进度直到其到达终止状态。用来确保某些活动直到其他活动都完成后才继续执行
CountDownLatch(int count)
- count:计数器,需要等待的事件数
- countDown:递减计数器,表示有一个事件已经发生
- await:等待计数器达到零,表示所有事件都已经发生
5.5.2 FuntureTask
也可以用做闭锁。通过Callable实现,相当于可生成结果的Runnable,可处于等待运行、正在运行、运行完成状态
5.5.3 信号量
计数信号量(Counting Semaphore)用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。可用来实现资源池或对容器施加边界 Semaphore(int permits)
- permits:许可,执行操作时先获得许可,使用后释放许可
- acquire:阻塞直到有许可
- release:返回一个许可给信号量
5.5.4 栅栏
阻塞一组线程直到某个事件发生
区别:闭锁等待事件,栅栏等待其他线程
CyclicBarrier:并行迭代算法、模拟程序
Exchanger:两方栅栏,各方在栅栏位置交换数据。两方执行不对称操作(缓冲区写、读数据)