概念
线程池(Thread Pool)是一种并发编程中常用的技术,用于管理和重用线程。它由线程池管理器、工作队列和线程池线程组成。
线程池的基本概念是,在应用程序启动时创建一定数量的线程,并将它们保存在线程池中。当需要执行任务时,从线程池中获取一个空闲的线程,将任务分配给该线程执行。当任务执行完毕后,线程将返回到线程池,可以被其他任务复用。
这就好比影视剧的地牢里面的烙铁,不用的时候放在火盆里,用的是直接拿,用多少拿多少,这就减少了把烙铁加热的时间了。线程比作烙铁,线程池就像火盆,保持烙铁可以直接使用;
线程池的使用
那线程池又该怎么使用呢?这里咱们结合项目介绍。
1.建立ThreadPool的config来管理线程池
(注意:项目当中线程池尽量不要使用的时候再创建,不要再业务逻辑中创建,这样每次调用这个方法都会创建一个线程池,应该在项目启动的时候就创建好)
@Configuration
public class ThreadPoolConfig {
@Bean("labelThreadPool")
public ThreadPoolExecutor labelThreadPoolExecutor() {
return new ThreadPoolExecutor(20, 100, 5
, TimeUnit.SECONDS, new LinkedBlockingQueue<>(40)
, Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
}
}
这里我们通过配置类在启动时创建一个线程池对象并把它交给spring容器管理,这样使用时直接通过注入方式就可以使用了。
2.通过FutureTask在一个异步线程中执行需要的run方法
1、 FutureTask概念
FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提供 start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果。一个FutureTask 可以用来包装一个 Callable 或是一个runnable对象。因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit)给一个Excutor执行(excution)。
2、FutureTask使用场景
FutureTask可用于异步获取执行结果或取消执行任务的场景。通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutureTask的get方法异步获取执行结果,因此,FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。另外,FutureTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTask的执行等。
@SneakyThrows
@Override
public List<SubjectCategoryBO> queryCategoryAndLabel(SubjectCategoryBO subjectCategoryBO) {
if (log.isInfoEnabled()) {
log.info("subjectCategoryBO:{}", JSON.toJSONString(subjectCategoryBO));
}
SubjectCategory subjectCategory = new SubjectCategory();
subjectCategory.setParentId(subjectCategoryBO.getId());
subjectCategory.setIsDeleted(isDeleteCode.NO_DELETE.getCode());
List<SubjectCategory> subjectCategoryList = subjectCategoryService.queryPrimaryCategory(subjectCategory);
List<SubjectCategoryBO> subjectCategoryBOList = SubjectCategoryConverter.INSTANCE.convertCategoryToBoList(subjectCategoryList);
//以上为代码可忽视
List<FutureTask<Map<Long,SubjectCategoryBO>>> futureTaskList = new LinkedList<>();
subjectCategoryBOList.forEach(
category -> {
//创建一个futuretask用来存储任务
FutureTask<Map<Long, SubjectCategoryBO>> futureTask = new FutureTask<>(()->
getLabelList(category)
);
//存储在任务集合里面,方便取结果
futureTaskList.add(futureTask);
//调用线程池运行任务
labelThreadPool.submit(futureTask);
}
);
//通过futuretask的get获取任务运行结果
HashMap<Long, SubjectCategoryBO> map = new HashMap<>();
for (FutureTask<Map<Long, SubjectCategoryBO>> task : futureTaskList) {
Map<Long, SubjectCategoryBO> categoryBOMap = task.get();
if(CollectionUtils.isEmpty(categoryBOMap)){
continue;
}
map.putAll(categoryBOMap);
}
//以下代码可忽视
for (SubjectCategoryBO categoryBO : subjectCategoryBOList) {
SubjectCategoryBO bo = map.get(categoryBO.getId());
if(bo == null){
continue;
}
categoryBO.setLabelBOList(bo.getLabelBOList());
}
return subjectCategoryBOList;
}
标签:创建,FutureTask,任务,结合,线程,futureTask,new,执行
From: https://blog.csdn.net/2301_76760557/article/details/142553137