并发篇

1. 线程状态

要求

六种状态及转换

Image

分别是

其它情况(只需了解)

  • 可以用 interrupt() 方法打断等待有时限等待的线程,让它们恢复为可运行状态
  • park,unpark 等方法也可以让线程等待和唤醒

五种状态

五种状态的说法来自于操作系统层面的划分

Image

2. 线程池

要求

七大参数

  1. corePoolSize 核心线程数目 - 池中会保留的最多线程数
  2. maximumPoolSize 最大线程数目 - 核心线程+救急线程的最大数目
  3. keepAliveTime 生存时间 - 救急线程的生存时间,生存时间内没有新任务,此线程资源会释放
  4. unit 时间单位 - 救急线程的生存时间单位,如秒、毫秒等
  5. workQueue - 当没有空闲核心线程时,新来任务会加入到此队列排队,队列满会创建救急线程执行任务
  6. threadFactory 线程工厂 - 可以定制线程对象的创建,例如设置线程名字、是否是守护线程等
  7. handler 拒绝策略 - 当所有线程都在繁忙,workQueue 也放满时,会触发拒绝策略
    1. 抛异常 java.util.concurrent.ThreadPoolExecutor.AbortPolicy
    2. 由调用者执行任务 java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy
    3. 丢弃任务 java.util.concurrent.ThreadPoolExecutor.DiscardPolicy
    4. 丢弃最早排队任务 java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy

Image

代码说明

day02.TestThreadPoolExecutor 以较为形象的方式演示了线程池的核心组成

3. wait vs sleep

要求

一个共同点,三个不同点

共同点

不同点

4. lock vs synchronized

要求

三个层面

不同点

公平锁

条件变量

代码说明

  • day02.TestReentrantLock 用较为形象的方式演示 ReentrantLock 的内部结构

5. volatile

要求

原子性

可见性

有序性

代码说明

  • day02.threadsafe.AddAndSubtract 演示原子性
  • day02.threadsafe.ForeverLoop 演示可见性
    • 注意:本例经实践检验是编译器优化导致的可见性问题
  • day02.threadsafe.Reordering 演示有序性
    • 需要打成 jar 包后测试
  • 请同时参考视频讲解

6. 悲观锁 vs 乐观锁

要求

对比悲观锁与乐观锁

代码说明

  • day02.SyncVsCas 演示了分别使用乐观锁和悲观锁解决原子赋值
  • 请同时参考视频讲解

7. Hashtable vs ConcurrentHashMap

要求

更形象的演示,见资料中的 hash-demo.jar,运行需要 jdk14 以上环境,进入 jar 包目录,执行下面命令

java -jar --add-exports java.base/jdk.internal.misc=ALL-UNNAMED hash-demo.jar

Hashtable 对比 ConcurrentHashMap

ConcurrentHashMap 1.7

ConcurrentHashMap 1.8

8. ThreadLocal

要求

作用

原理

每个线程内有一个 ThreadLocalMap 类型的成员变量,用来存储资源对象

ThreadLocalMap 的一些特点

弱引用 key

ThreadLocalMap 中的 key 被设计为弱引用,原因如下

内存释放时机