jdk线程池就是使用jdk线程工具类ThreadPoolExecutor 创建线程池
spring线程池就是使用自己配置的线程池,然后交给spring处理,可以采用Async,也可以引入线程池的bean依赖。
记一下线程池优化不当导致的资源耗尽
原本接口业务逻辑
ExecutorService executorService = Executors.newFixedThreadPool(10);
CountDownLatch countDownLatch = new CountDownLatch(subjectList.size());
try {
for (Subject subject : subjectList) {
Member finalMember = member;
executorService.execute(() -> {
//耗时操作...
content.add(subjectMap);
countDownLatch.countDown();
});
}
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
由于该接口访问频率很频繁,每次访问会创建新的线程池,另外接口的循环内部不断创建线程处理,导致访问次数多了系统内部资源耗尽。
解决优化:
1、配置线程池,这样不用每次创建新的线程池
@Configuration
@EnableAsync
public class TaskExecutorConfig {
@Bean("taskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(10);
// 设置最大线程数
executor.setMaxPoolSize(30);
// 设置队列容量
executor.setQueueCapacity(Integer.MAX_VALUE);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("member-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
2、接口内部逻辑不变,也是循环创建线程处理,但是此时线程池处理不过来可以放入队列中缓冲
处理,这样不用无限创建线程,避免了内存耗尽,但是效率明显不如上面的。
@Autowired
private TaskExecutor taskExecutor;
List> content = Lists.newArrayList();
CountDownLatch countDownLatch = new CountDownLatch(subjectList.size());
for (Subject subject : subjectList) {
Member finalMember = member;
taskExecutor.execute(() -> {
this.asyncSubject(subject, finalMember, loginName, content, countDownLatch);
});
}