使用线程池查询数据
操作流程
- 查询出表的数据总量。
- 数据的切分,根据本机CPU的核数配置合适数量的线程处理数,根据数据总量为不同的线程分配不同的查询数据量分段,即不同的线程查询不同分段的数据。
- 将各个查询数据的线程提交至线程池,这里使用的线程是带有返回结果的异步线程。(这样能把所有查询结果合并,才能进行下一步的操作。拿不到处理后的数据还怎么做下一步操作呢,所以一点要选择带有返回结果的线程)
具体实现
controller层查询数据
@GetMapping("count")
public ResultJson getCount(){
MultiThreadQueryUtil multiThreadQueryUtil=new MultiThreadQueryUtil();
List<List> count=multiThreadQueryUtil.getMultiCombineResult();
return ResultJson.ok(count);
}
最主要的是是使用MultiThreadQueryUtil这个类中的getMultiCombineResult()方法进行数据查询
MultiThreadQueryUtil类
@Component
public class MultiThreadQueryUtil {
public static SpringContextUtil springContextUtil = new SpringContextUtil();
public List<List> getMultiCombineResult(){
List<List> result = new ArrayList<>();
UserMapper userMapper= (UserMapper) springContextUtil.getBean("userMapper");
int count=userMapper.selectCount(null);
List<Callable<List>> tasks = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
Callable<List> qfe = new ThredQuery((i-1)*5,5);
tasks.add(qfe);
}
try{
//定义固定长度的线程池 防止线程过多,6就够用了
ExecutorService executorService = Executors.newFixedThreadPool(6);
//Future用于获取结果
List<Future<List>> futures=executorService.invokeAll(tasks);
//处理线程返回结果
if(futures!=null&&futures.size() > 0){
for (Future<List> future:futures){
result.addAll(future.get());
}
}
//关闭线程池,一定不能忘记
executorService.shutdown();
}catch (Exception e){
e.printStackTrace();
}
return result;
}
}
由于要回查询的结果,所以使用实现 Callable接口的方式来建立线程创建查询任务
ThredQuery类
public class ThredQuery implements Callable<List> {
public static SpringContextUtil springContextUtil = new SpringContextUtil();
private int start;
private int end;
//每个线程查询出来的数据集合
private List datas;
public ThredQuery(int start,int end) {
this.start=start;
this.end=end;
//每个线程查询出来的数据集合
UserMapper userMapper= (UserMapper) springContextUtil.getBean("userMapper");
List count = userMapper.getUserLimit(start,end);
datas = count;
}
//返回数据给Future
@Override
public List call() throws Exception {
return datas;
}
}
List count = userMapper.getUserLimit(start,end);
mapper层进行分页查询将查询全部数据分为分页查询,每个线程查询相应数量条数的数据。
最后将数据汇总到一起。
SpringContextUtil
public class SpringContextUtil {
private static ApplicationContext applicationContext;
// 设置上下文
public static void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}
// 获取上下文
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
// 通过名字获取上下文中的bean
public static Object getBean(String name) {
if(name == null || name.length()==0) {
return null;
}
try {
String beanName = "";
if(name.length() >1){
beanName = name.substring(0, 1).toLowerCase() + name.substring(1);
} else {
beanName = name.toLowerCase();
}
return applicationContext.getBean(beanName);
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
// 通过类型获取上下文中的bean
public static <T> T getBean(Class<T> clazz) {
try {
return (T) applicationContext.getBean(clazz);
} catch(Exception ex) {
ex.printStackTrace();
return null;
}
}
}
测试结果
请求查询的方法
可见数据全部都查了来