1. 引言:为什么需要多线程
现代计算机普遍采用多核 CPU,单线程程序无法充分利用硬件资源。在服务端领域,高并发、低延迟是核心诉求,多线程成为必然选择。Java 从语言层面提供了强大的多线程支持(java.lang.Thread),并在 java.util.concurrent 包中提供了丰富的并发工具。但多线程也带来了线程安全、死锁、上下文切换开销等问题,因此理解其适用场景至关重要。
2. 异步处理:提升系统响应速度
2.1 场景描述
在 Web 应用中,某些操作耗时较长且不需要立即返回结果给客户端,例如用户注册成功后发送欢迎邮件、短信通知,或者记录操作日志。如果在请求线程中同步执行这些操作,会延长接口响应时间,降低用户体验。
2.2 实现方案
将耗时操作提交到独立的线程池中异步执行,主线程立即返回成功响应。
@RestController
public class UserController {
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@PostMapping("/register")
public String register(User user) {
// 保存用户到数据库(同步)
userService.save(user);
// 异步发送邮件
taskExecutor.submit(() -> emailService.sendWelcomeMail(user));
return "注册成功";
}
}
2.3 注意事项
- 线程池配置:需合理设置核心线程数、最大线程数、队列容量,避免资源耗尽。
- 异常处理:异步任务中的异常需捕获并记录,否则可能被吞没。
- 事务边界:异步操作无法与主线程共享事务,需独立处理一致性。
- 使用 CompletableFuture:Java 8 后推荐使用
CompletableFuture进行异步编程,支持链式调用和组合。
CompletableFuture.runAsync(() -> emailService.sendWelcomeMail(user), executor);
3. 并行计算:充分利用多核 CPU
3.1 场景描述
处理大量数据时,例如统计百万级用户的消费总额、生成复杂报表、图像处理、机器学习特征工程等,单线程耗时过长。通过将数据分片,多线程并行处理,最后合并结果。
3.2 实现方案
- Fork/Join 框架:适用于可递归拆分的任务(如归并排序)。
- 并行流:对集合使用
parallelStream(),底层使用 ForkJoinPool。 - 手动分片 + 线程池:将数据分割成若干块,提交给线程池处理,使用
CountDownLatch或CompletableFuture等待完成。

