Java多线程分页查询数据库_java使⽤多线程查询⼤批量数据前⾔
在某些时候,⼀旦单表数据量过⼤,查询数据的时候就会变得异常卡顿,虽然在⼤多数情况下并不需要查询所有的数据,⽽是通过分页或缓存的形式去减少或者避免这个问题,但是仍然存在需要这样的场景,⽐如需要导出⼀⼤批数据到excel中,导出数据之前,⾸先得把数据查询出来吧?这个查询的过程,数据量⼀旦过⼤,单线程查询数据将会成为瓶颈,下⾯尝试使⽤多线程来尝试查询⼀张数据量较⼤的表
由于代码逻辑不是很难,直接上代码,关键的地⽅会有代码注释和说明,总体实现思路:
查询表的数据总量
线程切分,根据本机CPU的核数配置合适数量的线程处理数,根据数据总量为不同的线程分配不同的查询数据量分段,即不同的线程查询不同分段的数据
将各个查询数据的线程提交⾄线程池,这⾥使⽤的线程是带有返回结果的异步线程
1、测试控制器
@GetMapping("/getSysLogMulti")
@ApiOperation(value = "多线程获取⽇志数据", notes = "多线程获取⽇志数据", produces = "application/json")
public List getSysLogMulti() {
SysLogMulti();
}
2、业务实现类
@Autowired
private MultiThreadQueryUtil multiThreadQueryUtil;
@Override
public ListgetSysLogMulti(){
MultiCombineResult();
}
3、多线程实现类
import com.sx.workflow.mapper.WorkflowTaskMapper;
import com.sx.workflow.util.ExcelLocalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import urrent.Callable;
import urrent.ExecutorService;
import urrent.Executors;
import urrent.Future;
/**
* 多线程查询结果
*/
@Service
public class MultiThreadQueryUtil {
@Autowired
private WorkflowTaskMapper workflowTaskMapper;
/**
* 获取多线程结果并进⾏结果合并
* @return
*/
public ListgetMultiCombineResult() {
//开始时间
long start = System.currentTimeMillis();
//返回结果
Listresult = new ArrayList<>();
//查询数据库总数量
int count = workflowTaskMapper.selectCountAll();
MapsplitMap = SplitMap(count,5);
int bindex = 1;
//Callable⽤于产⽣结果
List> tasks = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
//不同的线程⽤户处理不同分段的数据量,这样就达到了平均分摊查询数据的压⼒String[] nums = (String.valueOf(i)).split(":");
int startNum = Integer.valueOf(nums[0]);
int endNum = Integer.valueOf(nums[1]);
Callableqfe = new ThredQuery(startNum, endNum-startNum+1);
tasks.add(qfe);
bindex += bindex;
}
try{
/
/定义固定长度的线程池 防⽌线程过多,这个数量⼀般跟⾃⼰电脑的CPU核数进⾏匹配ExecutorService executorService = wFixedThreadPool(5);
//Future⽤于获取结果
List> futures=executorService.invokeAll(tasks);
//处理线程返回结果
if(futures!=null&&futures.size() > 0){
for (Futurefuture:futures){
result.());
}
}
//关闭线程池,⼀定不能忘记
executorService.shutdown();
}catch (Exception e){
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("线程查询数据⽤时:"+(end-start)+"ms");
return result;
}
}
4、不同的线程负责查询⾃⼰线程负责的数据分段的数据⽅法
public class ThredQuery implements Callable{
public static SpringContextUtil springContextUtil = new SpringContextUtil();
private int start;
private int end;
//每个线程查询出来的数据集合
private List datas;
public ThredQuery(int start,int end) {
this.start=start;
//每个线程查询出来的数据集合
WorkflowTaskService workflowTaskService = Bean("workflowTaskService"); List count = CurrentTasks(start,end);
datas = count;
}
//返回数据给Future
@Override
public List call() throws Exception {
return datas;
}
}
怎么大批量数据核对差异获取具体的bean的⼯具类,由于线程中⽆法注册bean,因此需要通过获取bean的⽅式来进⾏数据库查询和交互,代码如下:
import org.springframework.beans.BeansException;
import t.ApplicationContext;
import t.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component("springContextUtil")
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext; // Spring应⽤上下⽂环境
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
@SuppressWarnings("unchecked")
public static T getBean(String name) throws BeansException {
return (T) Bean(name);
}
@SuppressWarnings("unchecked")
public static T getBean(Class> clz) throws BeansException {
return (T) Bean(clz);
}
}
最后运⾏⼀下程序,通过接⼝来调⽤⼀下,通过执⾏结果可以看到,我这⾥单表⼤概5万多条数据,测试了⼏次,平均下来,不到2秒的时间,总体来说,还是很快的
本篇内容⽐较简单,主要是⽅便后续使⽤时查阅,希望对看到的同学有⽤,最后感谢观看!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论