第 8 周:多线程与线程池
本周目标
本周解决“同时做多件事”的问题。完成后,应能够:
- 说明进程与线程、并发与并行的区别
- 使用三种方式创建线程,并使用
Callable获取返回值 - 复现线程安全问题并说明产生原因
- 使用同步代码块、
Lock和原子类保证线程安全 - 使用线程池管理线程并说明核心参数的作用
- 使用定时任务处理周期性工作
学习资料与范围
- 主课程:Java 零基础视频教程(下部)
- 视频范围:下部“多线程”章节
| 学习模块 | 学习结果 |
|---|---|
| 线程创建与生命周期 | 能够使用三种方式创建并启动线程 |
| 线程安全与同步 | 能够复现并修复共享数据错误 |
Lock 与线程通信 | 能够使用锁和等待唤醒机制 |
Callable、Future 与 FutureTask | 能够获取线程执行结果 |
| 线程池与定时器 | 能够使用线程池和定时任务 |
| 并发基础概念 | 能够说明原子性、可见性、有序性 |
需要掌握的知识点
线程基础
- 进程、线程、并发、并行的区别
- 创建线程的三种方式:继承
Thread、实现Runnable、实现Callable start()与run()的区别- 线程生命周期:新建、就绪、运行、阻塞、结束
Thread常用方法:sleep、join、setName、setDaemon、setPriority- 线程的优先级和名称在调试中的作用
- 主线程与子线程的执行顺序不可假设
线程安全
- 共享可变数据是线程安全问题的根源
- 复现问题:多线程对同一变量累加,结果少于预期
- 同步代码块、同步方法和锁对象的作用
synchronized的锁对象选择:不要锁字符串常量,尽量使用 final 对象Lock接口与ReentrantLock的基本用法,lock()与unlock()的配对- 死锁的产生条件和避免方式:固定加锁顺序、减少锁范围
- 原子类
AtomicInteger的作用和使用场景 - 原子性、可见性、有序性的基本含义
volatile能解决什么、不能解决什么- 等待唤醒机制(
wait/notify)的基本思路,了解生产者消费者模型
线程池与定时器
- 线程池的作用:复用线程、控制并发数量、统一管理任务
ThreadPoolExecutor的核心参数:核心线程数、最大线程数、空闲存活时间、任务队列、拒绝策略- 为什么推荐手动创建线程池而不是无脑使用
Executors execute()与submit()的区别Callable与Future:提交任务、获取结果、处理异常、超时控制- 定时器:
Timer的局限与ScheduledExecutorService的用法 - 线程池的关闭:
shutdown()与shutdownNow() - 并发集合
ConcurrentHashMap的使用场景(了解)
必做练习
- 三种创建方式:分别使用继承
Thread、实现Runnable、Lambda 创建并启动线程,输出线程名称。 - 执行顺序:启动 3 个线程分别打印 1-5,观察每次运行结果顺序不同并解释原因。
- 线程安全复现:开启 10 个线程对同一变量累加 1000 次,输出实际结果并说明为什么小于 10000。
- 三种修复方案:分别使用同步代码块、
ReentrantLock和AtomicInteger修复上一题,并对比耗时。 - 死锁复现:编写两个线程互相等待对方的锁,复现死锁并说明预防方式。
- 带返回值的任务:使用
Callable与Future让 3 个线程分别统计一部分成绩,再汇总结果。 - 线程池基础:手动创建线程池,提交 20 个任务并输出执行顺序和线程名称。
- 参数实验:修改核心线程数和队列长度,记录任务排队和执行情况的变化。
- 定时任务:使用
ScheduledExecutorService每 2 秒输出一次统计信息,运行 10 秒后关闭。 - 并发集合:在多线程环境下分别向
HashMap和ConcurrentHashMap写入数据,记录现象差异。 - 安全测试:为并发统计方法编写测试,重复运行多次,确认结果稳定。
本周综合任务:并发批量导入与导出
为项目增加批量数据导入导出功能,并使用多线程加速。
要求:
- 支持从文本文件批量导入学生数据,数据量大时分成若干批次处理
- 使用线程池并发处理批次,批次大小和线程数量可配置
- 使用
Future汇总各批次的成功条数和失败条数,最终输出导入报告 - 对导入失败的记录输出具体原因(学号重复、成绩非法、格式错误)
- 保证并发写入集合时的线程安全,说明采用的方案和理由
- 使用定时任务输出一次导入进度,任务结束后正确关闭线程池
- 为批量导入编写测试,验证结果与单线程导入一致
- 记录一次线程安全问题的复现过程和修复对比
本周产出
- 线程创建、线程安全和线程池练习代码
- 并发批量导入导出功能及导入报告
- 线程安全问题复现与修复记录
- 线程池参数实验记录
- 一份多线程与线程池笔记(含参数含义和常见坑)
完成检查
- 能够使用三种方式创建线程并说明区别
- 能够复现线程安全问题并解释原因
- 能够使用同步代码块、
Lock或原子类修复线程安全问题 - 能够说明死锁的产生条件和避免方式
- 能够使用
Callable和Future获取线程执行结果 - 能够手动创建线程池并说明核心参数含义
- 能够使用定时任务并在结束时关闭线程池
- 已完成并发批量导入功能,结果与单线程一致