Spring对多线程的支持
Spring框架通过TaskExecutor和TaskScheduler接口提供了对多线程的支持,简化了异步任务和定时任务的开发。核心线程池实现基于Java的ExecutorService,但提供了更高级的抽象和集成。
Spring内置的线程池类型及使用场景
1. ThreadPoolTaskExecutor
-
特点 :基于Java的
ThreadPoolExecutor实现,支持核心线程数、最大线程数、队列容量等配置。 -
场景:适用于需要控制并发量的业务场景,如批量处理任务、高并发请求分发。
-
配置示例 :
java@Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); return executor; }
2. SimpleAsyncTaskExecutor
- 特点:每次请求都会新建一个线程,不复用线程。
- 场景:适合轻量级的异步任务,但需注意线程泄漏风险,不建议生产环境高频使用。
3. ConcurrentTaskExecutor
- 特点 :包装现有的
Executor或ExecutorService实例。 - 场景:需要复用已有线程池或与其他库(如CompletableFuture)集成时使用。
4. ThreadPoolTaskScheduler
- 特点 :支持定时任务和周期性任务,内部使用
ScheduledExecutorService。 - 场景:定时任务调度,如定期数据同步、心跳检测。
5. SyncTaskExecutor
- 特点:同步执行任务,无异步效果。
- 场景:测试或需要强制同步执行的场景。
使用多线程的注意事项
线程安全问题
- 避免共享可变状态,使用线程安全的数据结构(如
ConcurrentHashMap)。 - 对共享资源加锁时,注意锁粒度,防止死锁。
资源管理
- 线程池参数需根据业务负载调整,避免队列积压或线程过多导致OOM。
- 使用
@Async时,需通过@EnableAsync启用,并指定自定义的TaskExecutor。
异常处理
- 异步任务需单独捕获异常,避免因未捕获异常导致线程终止。
- 实现
AsyncUncaughtExceptionHandler处理@Async方法的异常。
事务传播
- 异步方法内的事务默认不传播,需通过
PROPAGATION_REQUIRES_NEW等方式显式管理。
上下文传递
-
Spring的
ThreadPoolTaskExecutor默认不传递线程上下文(如SecurityContext),需配置TaskDecorator。javaexecutor.setTaskDecorator(runnable -> { SecurityContext context = SecurityContextHolder.getContext(); return () -> { SecurityContextHolder.setContext(context); runnable.run(); }; });
最佳实践建议
- 监控线程池 :通过
ThreadPoolExecutor的API或Micrometer监控活跃线程、队列大小等指标。 - 避免阻塞IO:长时间阻塞任务应使用独立的线程池,避免影响核心业务线程。
- 合理关闭 :应用关闭时调用
executor.shutdown()等待任务完成。