前言

在开发过程中可能会碰到某些独特的业务,比如查询全部表数据,数据量过多会导致查询变得十分缓慢。虽然在大多数情况下并不需要查询所有的数据,而是通过分页或缓存的形式去减少或者避免这个问题,但是仍然存在需要这样的场景,比如需要导出所有的数据到excel中,导出数据之前,肯定需要先查询表中数据,这个查询的过程中数据量一旦过大,单线程查询数据会严重影响程序性能,有可能过长的查询时间导致服务宕机。现在模拟使用多线程来查询一张数据量较大的表。


提示:以下是本篇文章正文内容,下面案例可供参考

一、什么是线程,什么是线程池

这一块内容就不再做过多的赘述,本文章只是直接使用案例来使用它们。不太了解的可自行百度查一下。

二、使用步骤

  1. 查询出表的数据总量。
  2. 数据的切分,根据本机CPU的核数配置合适数量的线程处理数,根据数据总量为不同的线程分配不同的查询数据量分段,即不同的线程查询不同分段的数据。
  3. 将各个查询数据的线程提交至线程池,这里使用的线程是带有返回结果的异步线程。(这样能把所有查询结果合并,才能进行下一步的操作。拿不到处理后的数据还怎么做下一步操作呢,所以一点要选择带有返回结果的线程)

controller层:

    @GetMapping("/getAllData")@ApiOperation(value = "多线程获取日志数据",)public class MultiThreadController {@Autowiredprivate ThredService thredService;@GetMapping("/testThredData")public List testThredData(){return thredService.getAllResult();}
}

service层:

  public interface ThredService {public List getAllResult();}

serviceImpl层:

@Service
public class  ThredServiceImpl implements ThredService {@Autowiredprivate MultiThreadQueryUtil multiThreadQueryUtil;@Overridepublic List getMultiCombineResult() {return multiThreadQueryUtil.getMultiCombineResult();}}

多线程实现类(核心)

@Service
public class MultiThreadQueryUtil {@Autowiredprivate WorkflowTaskMapper workflowTaskMapper;/*** 获取多线程结果并进行结果合并* @return*/public List<List> getMultiCombineResult() {//开始时间long start = System.currentTimeMillis();//返回结果List<List> result = new ArrayList<>();//查询数据库总数量int count = workflowTaskMapper.selectCountAll();Map<String,String> splitMap = ExcelLocalUtils.getSplitMap(count,5);int bindex = 1;//Callable用于产生结果List<Callable<List>> tasks = new ArrayList<>();for (int i = 1; i <= 5; i++) {//不同的线程用户处理不同分段的数据量,这样就达到了平均分摊查询数据的压力String[] nums = splitMap.get(String.valueOf(i)).split(":");int startNum = Integer.valueOf(nums[0]);int endNum = Integer.valueOf(nums[1]);Callable<List> qfe = new ThredQuery(startNum, endNum-startNum+1);tasks.add(qfe);bindex += bindex;}try{//定义固定长度的线程池  防止线程过多,5就够用了ExecutorService executorService = Executors.newFixedThreadPool(5);//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();}long end = System.currentTimeMillis();System.out.println("线程查询数据用时:"+(end-start)+"ms");return result;}}

不同的线程负责查询自己线程负责的数据分段的数据方法
也就是你的业务处理方法:

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;//每个线程查询出来的数据集合QueryService queryService= springContextUtil.getBean("queryService");List count = queryService.getQueryData(start,end);datas = count;}//返回数据给Future@Overridepublic List call() throws Exception {return datas;}}

总结

商品表大概7万多条数据,测试了几次,平均下来,不到3秒的时间,如果不这样写,单线程查询出来的数据大概是9s左右。

源码:

点击此处跳转源码地址

JAVA使用线程池查询大批量数据相关推荐

  1. java异步线程池同时请求多个接口数据

    java异步线程池同时请求多个接口数据 一.适合的使用场景 复杂的网页爬虫,如要同时请求多个不同网页的数据,并且需要执行不同的数据处理,这个是非常合适的,执行线程传递的参数到最后callback是会附 ...

  2. Java常用线程池-固定线程池使用

    Java常用线程池-固定线程池使用 固定线程池 固定线程池 在执行数据处理时不可避免的需要使用多线程进行数据处理,以此提高数据处理效率,降低处理时间.而线城池现在池容器对数据处理效率提升有举足轻重的作 ...

  3. java中线程池的几种实现方式

    1.线程池简介:     多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.         假设一个服务器完成一项任务所需时间为:T1 ...

  4. Java 监控线程池所有任务是否执行完毕

    Java 监控线程池所有任务是否执行完毕 场景引入 在最近的工作中遇到一个需要批量生产百万数据并写入数据库的需求,先通过单线程的方式去实现,但是感觉效率一般,然后通过多线程的方式去改进,但是遇到下面的 ...

  5. 并发编程五:java并发线程池底层原理详解和源码分析

    文章目录 java并发线程池底层原理详解和源码分析 线程和线程池性能对比 Executors创建的三种线程池分析 自定义线程池分析 线程池源码分析 继承关系 ThreadPoolExecutor源码分 ...

  6. Java 自定义线程池

    Java 自定义线程池 https://www.cnblogs.com/yaoxiaowen/p/6576898.html public ThreadPoolExecutor(int corePool ...

  7. Java并发—线程池ThreadPoolExecutor基本总结

    原文作者:Matrix海子 原文地址:Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线 ...

  8. java定时线程池_java 定时器线程池(ScheduledThreadPoolExecutor)的实现

    前言 定时器线程池提供了定时执行任务的能力,即可以延迟执行,可以周期性执行.但定时器线程池也还是线程池,最底层实现还是ThreadPoolExecutor,可以参考我的另外一篇文章多线程–精通Thre ...

  9. Java中线程池,你真的会用吗

    转载自   Java中线程池,你真的会用吗 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Ex ...

最新文章

  1. Excel的vlookup函数的用法
  2. Matrix工作室第六届纳新AI组考核题(B卷)
  3. 从零开始编写自己的C#框架(25)——网站部署
  4. c#中计算三角形面积公式_看着有点迷的三角形面积计算
  5. Opencv中的阈值函数
  6. java仿qq登录 界面设计,Java Swing仿QQ登录界面效果
  7. 【select模块】select IO多路复用和select实现FTP
  8. 记一次 .NET 某电商定向爬虫 内存碎片化分析
  9. 超详细图解!【MySQL进阶篇】MySQL事务和锁
  10. 7-21 求特殊方程的正整数解 (15 分)
  11. 判断double_深入解析单例模式之懒汉模式---Double-Check及volatile关键字
  12. 如何解决struts2没有提示问题
  13. C++ unordered_map 在key为string类型和char*类型时测试时间性能差异
  14. 使用python读取excel
  15. Java、JSP电子书下载系统
  16. 新谈:为什么你觉得FPGA难学?如何入门?
  17. mysql全文索引使用
  18. idea 中部署 tomcat
  19. ImportError: cannot import name ‘bbox_ious‘
  20. 万能分页显示上一页下一页

热门文章

  1. JavaScript代码 在项目中高效、快速开发
  2. teraterm软件download的地址
  3. 基于eclipse的android项目实战—博学谷(四)底部导航栏
  4. SpringBoot不同角色显示不同的菜单
  5. coreutils8.32 whoami命令和源码分析
  6. [Rails应用实战]WebChat的敏捷开发
  7. 上海市迎来今年第二个租房高峰期
  8. php程序+打印机,PHP自动打印到网络打印机?
  9. edrawmax使用技巧备忘
  10. Libev源码分析08:Libev中的信号监视器