第一部分:线程创建方式
掌握Java中创建线程的4种方式
学习目标
理解并掌握继承Thread类、实现Runnable接口、实现Callable接口和使用线程池创建线程的方式
1. 继承Thread类
特点: 简单直接,但无法继承其他类
2. 实现Runnable接口
特点: 解耦任务与线程,可继承其他类
3. 实现Callable接口
特点: 支持返回值,可抛出异常
4. 使用线程池
特点: 高效资源管理,避免频繁创建销毁
创建方式对比
方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
继承Thread | 简单直接 | 无法继承其他类 | 简单任务 |
实现Runnable | 解耦任务与线程 | 无返回值 | 大多数场景 |
实现Callable | 支持返回值 | 使用复杂 | 需要返回结果 |
线程池 | 高效资源管理 | 配置复杂 | 生产环境 |
第二部分:线程生命周期
理解线程的6种状态及其转换
学习目标
掌握线程的6种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
新建
可运行
阻塞
等待
限时等待
终止
NEW(新建)
线程被创建但未启动时的状态
创建方式: new Thread()
转换条件: 调用start()方法进入RUNNABLE状态
RUNNABLE(可运行)
线程正在运行或准备运行的状态
包含: 就绪(Ready)和运行中(Running)
转换条件: 时间片用完或主动放弃进入BLOCKED/WAITING
BLOCKED(阻塞)
等待获取锁时的状态
触发条件: 进入synchronized方法/块
转换条件: 获取到锁后进入RUNNABLE状态
WAITING(等待)
无限期等待其他线程操作
触发方法: Object.wait(), Thread.join()
转换条件: 被notify()/notifyAll()唤醒
TIMED_WAITING(限时等待)
有限时间等待状态
触发方法: Thread.sleep(), Object.wait(timeout)
转换条件: 时间结束或被唤醒
TERMINATED(终止)
线程执行结束后的状态
触发条件: run()方法执行完成
转换条件: 不可再启动
状态监控技巧
1. 使用jstack工具查看线程状态
2. 在IDEA中通过调试视图查看线程状态
3. Thread.getState()方法获取状态
4. 避免线程长时间处于BLOCKED/WAITING状态
第三部分:线程同步(synchronized)
掌握synchronized关键字的使用
学习目标
理解synchronized的原理、使用方式及常见问题
synchronized关键字
Java内置同步机制,简单易用
优点: 自动释放锁,无需手动管理
缺点: 功能有限,无法中断等待锁的线程
锁升级过程
Java 6引入的锁优化机制
- 偏向锁:适用于只有一个线程访问的场景
- 轻量级锁:适用于线程交替执行的场景
- 重量级锁:适用于多线程竞争的场景
优点: 根据竞争情况自动升级锁
缺点: 锁升级不可逆
常见错误
1. 锁对象错误:使用可变对象或基本类型作为锁
2. 锁范围过大:同步整个方法或大段代码
3. 死锁问题:多个线程互相持有对方需要的锁
4. 忘记释放锁:synchronized会自动释放
第四部分:Lock锁与ReentrantLock
掌握Lock接口的使用及ReentrantLock特性
学习目标
理解Lock接口的核心方法、ReentrantLock的可重入性、公平锁和非公平锁的区别
Lock接口核心方法
- lock() - 获取锁
- unlock() - 释放锁
- tryLock() - 尝试获取锁
- lockInterruptibly() - 可中断获取锁
- newCondition() - 创建Condition对象
ReentrantLock使用
公平锁与非公平锁
公平锁: 按照线程请求顺序获取锁
非公平锁: 允许插队,性能更高
Lock与synchronized对比
特性 | synchronized | Lock |
---|---|---|
实现方式 | JVM内置 | Java代码实现 |
锁获取 | 自动获取释放 | 手动获取释放 |
可中断 | 不支持 | 支持 |
公平锁 | 不支持 | 支持 |
超时获取 | 不支持 | 支持 |
第五部分:线程通信(wait/notify)
掌握线程间协作机制
学习目标
理解wait(), notify(), notifyAll()方法的使用及生产者-消费者模式
wait()方法
使当前线程进入等待状态,释放锁
使用条件: 必须在同步块内调用
notify()方法
唤醒在此对象监视器上等待的单个线程
使用条件: 必须在同步块内调用
notifyAll()方法
唤醒在此对象监视器上等待的所有线程
使用条件: 必须在同步块内调用
常见错误
1. 在非同步块内调用wait/notify
2. 使用if而不是while检查条件
3. 忘记调用notify/notifyAll
4. 错误使用notify而不是notifyAll
5. 忽略InterruptedException
第六部分:线程池(ExecutorService)
掌握线程池的使用及核心参数
学习目标
理解线程池的工作原理、核心参数及常见线程池类型
核心参数
- corePoolSize:核心线程数
- maxPoolSize:最大线程数
- keepAliveTime:空闲线程存活时间
- workQueue:任务队列
- threadFactory:线程工厂
- handler:拒绝策略
常见线程池
- newFixedThreadPool:固定大小线程池
- newCachedThreadPool:可缓存线程池
- newSingleThreadExecutor:单线程线程池
- newScheduledThreadPool:定时任务线程池
拒绝策略
- AbortPolicy:抛出RejectedExecutionException
- CallerRunsPolicy:由调用线程执行任务
- DiscardPolicy:直接丢弃任务
- DiscardOldestPolicy:丢弃队列最前面的任务
最佳实践
1. 使用ThreadPoolExecutor而不是Executors创建线程池
2. 根据任务类型设置合理的线程数
3. 使用有界队列防止内存溢出
4. 设置合理的拒绝策略
5. 使用shutdown()关闭线程池
第七部分:Callable与Future
掌握带返回值的异步任务处理机制
学习目标
理解Callable接口、Future接口及FutureTask的使用
Callable接口
带返回值的任务接口
特点: 支持返回值,可抛出异常
Future接口
表示异步计算的结果
特点: 可取消任务,可获取结果
FutureTask
Future接口的实现类
CompletableFuture
Java 8增强的异步编程API
第八部分:综合测试
通过测试巩固多线程知识
问题1:线程创建方式
正确创建线程池的方式是使用Executors工厂类或ThreadPoolExecutor构造函数
问题2:线程状态
Thread.sleep()方法会使线程进入TIMED_WAITING状态
问题3:synchronized
synchronized不支持中断等待,Lock接口才支持中断
问题4:Lock锁
tryLock()可以尝试获取锁,避免无限期等待
问题5:线程通信
当队列满时,生产者应该调用wait()方法等待
问题6:线程池
拒绝策略在队列满且线程数达到maxPoolSize时触发
知识总结
1. 线程创建:掌握4种创建方式及适用场景
2. 线程状态:理解6种状态及其转换条件
3. 线程同步:掌握synchronized和Lock的使用及区别
4. 线程通信:理解wait/notify机制及生产者-消费者模式
5. 线程池:掌握线程池参数配置及使用方式
6. Callable/Future:掌握带返回值的异步任务处理

Java多线程核心知识图谱