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:两方栅栏,各方在栅栏位置交换数据。两方执行不对称操作(缓冲区写、读数据)

5.6 构建高效且可伸缩的结果缓存