SpringBoot用线程池ThreadPoolExecutor处理百万级数据

2023-10-27

SpringBoot用线程池ThreadPoolExecutor处理百万级数据

 更多优秀文章,请扫码关注个人微信公众号或搜索“程序猿小杨”添加。

一、背景:

     使用JDK线程池ThreadPoolExecutor多线程异步执行批量插入、更新等操作方法,提高百万级数据插入效率。

二、具体细节:

2.1、创建自适应机器本身线程数量的线程池

//创建自适应机器本身线程数量的线程池    Integer processNum = Runtime.getRuntime().availableProcessors();    int corePoolSize = (int) (processNum / (1 - 0.2));    int maxPoolSize = (int) (processNum / (1 - 0.5));    ExecutorService executorService = new ThreadPoolExecutor(            corePoolSize,            maxPoolSize,            2L,            TimeUnit.SECONDS,            new LinkedBlockingQueue<>(3),            Executors.defaultThreadFactory(),            new ThreadPoolExecutor.CallerRunsPolicy()    );    @Override    public boolean batchInsert(List<Student> list) throws Exception {        Future<Boolean> a = null;        try {            /**             * submit与execute 都是向线程池提交任务。             * submit提交后执行提交类实现callable方法后重写的call方法,execute提交后执行实现Runnable的run方法             * Runnable任务没有返回值,而Callable任务有返回值。             * 并且Callable的call()方法只能通过ExecutorService的submit(Callable <T> task) 方法来执行             * 多人同时提交时的线程控制:多线程多任务             */            a = executorService.submit(new BatchWay(list,studentService));            return a.get();        } catch (Exception e) {            e.printStackTrace();            try {                return a.get();            } catch (Exception ex) {                ex.printStackTrace();                return false;            }        }    }

2.2、业务核心处理类:

@Slf4jpublic class BatchWay implements Callable<Boolean> {    private int batch100 = 100;  //100条为分界批量导入    private List<Student> list; //list中的大量数据    private StudentService studentService;
    //有参的构造函数,方便初始化其类    public BatchWay(List<Student> list, StudentService studentService) {        this.list = list;        this.studentService = studentService;    }    /**线程池*///    private ThreadPoolExecutor threadPoolExecutor =//            new ThreadPoolExecutor(//                    10, //corePoolSize:线程池中核心线程数//                    Runtime.getRuntime().availableProcessors(),  //线程池中能拥有最多线程数 取所有//                    5L,  //keepAliveTime:表示空闲线程的存活时间 2秒//                    TimeUnit.SECONDS, //表示keepAliveTime的单位:秒//                    new LinkedBlockingQueue<>(100),  //用于缓存任务的阻塞队列                    Executors.defaultThreadFactory(),//                    new ThreadPoolExecutor.CallerRunsPolicy()//            );    /**     * 功能描述:实现Callable的call方法     * @MethodName: call     * @MethodParam: []     * @Return: java.lang.Boolean     * @Author: yyalin     * @CreateDate: 2022/5/6 15:46     */    public Boolean call(){        try {            batchOp(list);            return true;        } catch (Exception e) {            e.printStackTrace();        }        return false;    }

    /**     * 功能描述:批量保存数据     * @MethodName: batchOp     * @MethodParam: [list]     * @Return: void     * @Author: yyalin     * @CreateDate: 2022/5/6 15:40     */    private void batchOp(List<Student> list) {        if(!list.isEmpty()){            Integer size = list.size();            if(size<=batch100){                //小于分批的直接插入即可                studentService.saveBatch(list);            }else if(size>batch100){                //分批后再进行保存数据                batchOpSpilit(list,batch100);            }        }    }

    /**     * 功能描述:对list进行切割     * @MethodName: batchOpSpilit     * @MethodParam: [list, batch100]     * @Return: void     * @Author: yyalin     * @CreateDate: 2022/5/6 15:43     */    private void batchOpSpilit(List<Student> list, int batch100) {        log.info("开始切割………………");        List<List<Student>> list1 = SplitListUtils.pagingList(list, batch100);        try {            for (List<Student> list2 : list1) {                batchOp(list2);//                threadPoolExecutor.allowCoreThreadTimeOut(true);//                //再调batchOp方法,这里的多线程是多个小集合往数据库插入//                threadPoolExecutor.execute(() -> {                    log.info("我是线程开始保存数据...:" + Thread.currentThread().getName());//                    batchOp(list2);//                });            }//            log.info("当前线程池剩余的数量222222:"+threadPoolExecutor.getPoolSize());        } catch (Exception e) {//            log.info("出现异常:"+e);        } finally {            //最后关闭线程 不允许提交新的任务,但是会处理完已提交的任务//            threadPoolExecutor.shutdown();        }    }

2.3、造数据,多线程异步插入:

  public String batchWay() throws Exception {        log.info("开始批量操作.........");        Random rand = new Random();        List<Student> list = new ArrayList<>();        for (int i = 0; i < 1000003; i++) {            Student student=new Student();            student.setStudentName("小李"+i);            student.setAddr("上海"+rand.nextInt(9) * 1000);            student.setAge(rand.nextInt(1000));            student.setPhone("134"+rand.nextInt(9) * 1000);            list.add(student);        }        long startTime = System.currentTimeMillis(); // 开始时间        boolean a=studentService.batchInsert(list);        long endTime = System.currentTimeMillis(); //结束时间        return "执行完成一共耗时time: " + (endTime - startTime) / 1000 + " s";    }

2.4、测试结果

汇总结果:

序号

核心线程(core_pool_size)

插入数据(万) 耗时(秒)
1 10 100w 38s
2 15 100w 32s
3 50 100w 31s

个人推荐:SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据的方法。

总结:ThreadPoolTaskExecutor和ThreadPoolExecutor比Executors创建线程池更加灵活,可以设置参数,推荐ThreadPoolTaskExecutor和ThreadPoolExecutor,而ThreadPoolTaskExecutor是ThreadPoolExecutor的封装,所以,性能更加优秀,推荐ThreadPoolTaskExecutor

更多优秀文章,请扫码关注个人微信公众号或搜索“程序猿小杨”添加。

推荐文章:

    1、SpringBoot使用@Async实现多线程异步;

    2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据;

    3、SpringBoot用线程池ThreadPoolExecutor处理百万级数据

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot用线程池ThreadPoolExecutor处理百万级数据 的相关文章

随机推荐

  • 03 - 大学生如何使用GPT

    大学生如何使用GPT提高学习效率 一 引言 在当今的高速发展的信息时代 大学生面临着越来越多的学习挑战 作为一种先进的人工智能技术 GPT为大学生提供了一种强大的学习工具 本文将介绍大学生在不同场景中如何使用GPT来提高学习效率 并给出一些
  • C++环形缓冲区的简单实现

    分享一个在工作中用到的简单的环形缓冲区 构造简单 可以改造到Qt中使用 也可以直接在VS下使用 所谓环形缓冲区 其实就是带有标识缓冲区中数据头 尾位置的缓冲区 这个缓冲区根据业务的不同 要设置的稍微大一点 不能一有数据过来就填满了 这样就失
  • SpringBoot整合常用Json框架-基础篇

    1 本篇概要 本文主要介绍如何在Spring Boot中整合3种常用的Json框架 包含Spring Boot本身提供的Jackson和Gson 以及国内常用的阿里巴巴开源Fastjson的整合 2 Json框架整合 2 1 整合 Jack
  • 一阶RC滤波器的算法实现(低通和高通)

    目前 项目需要处理信号 目标信号是特定频率范围内的信号 高频视为干扰 而一阶RC滤波器容易实现 但是网上资料往往没有详细的推导 因此在这里把笔记记下 本文的优势是比较详细 参数配置都有公式依据 目录 1 一阶RC低通滤波器的算法实现 1 1
  • 漏洞扫描器 XRAY

    文章目录 XRAY简介 XRAY安装 XRAY使用 爬虫模式 被动扫描 生成 ca 证书 开启监听 浏览器设置代理 访问网站自动探测漏洞 BurpSuite联动XRAY xray 开启端口监听 burpsuite 设置 通过burp sui
  • js 实现汉字简体和繁体之间的互相转换

    简体字 简体字 Simplified Chinese 简体中文 是中国大陆地区目前在用的字体 由官方公布的简体字 主要由传承字以及1950年代以后中华人民共和国政府开始在中国大陆地区推行的简化字所组成 目前 简体字的使用地区包括中国大陆 联
  • C++ 保存txt文本文件

    第一步 包含头文件 include
  • ExtJS 容器布局方式

    ExtJS是构建浏览器应用界面的框架 为开发人员提供了丰富UI组件 这些组件在页面中是以特定方式排列的 即布局方式 一个ExtJS构建的页面 无论看起来多么复杂 最终都能根据其布局拆分成许多小的区域 最近工作中的项目比较老旧 使用的是3 0
  • vue子组件向父组件传值的方法

    子组件向父组件 使用 emit方法 demo 子组件的代码
  • 【手把手 带你准备电赛】解答小课堂——串口通信和串行通信

    目录 串口通信和串行通信的定义 串口通信和串行通信的区别 串口通信和串行通信的联系 串口 串行 你分清楚这两个概念了吗 是不是还是串什么通信 串行通信 什么串口 不要担心 这篇文章 小蛋糕带你深入浅出分清串口通信和串行通信 串口通信和串行通
  • k线图中趋势线的画法精讲

    曾经有技术分析师大师把技术分析概括为一句话 那就是 一把直尺走天下 这是画线分析方法的直观和有效的高度概括 在众多的画线方法中 趋势线用以衡量贵金属的价格趋势 通过趋势线的方向可以明确地看出价格变动的方向 一 上升趋势线的画法 在上升趋势中
  • Ubuntu下pycharm的安装和卸载

    pycahrm安装 首先要去pycharm的官方网站下载Linux版本的pycharm安装包 如果想要下载以前版本的pycharm可以登录下方的网站去下载 https www jetbrains com pycharm download o
  • 按摩软件仿东郊到家系统开发,上门预约系统;

    按摩软件仿东郊到家系统开发 上门预约系统 用户端 技师端 商家端 以及管理后台 上门预约的操作 1 技师管理 技师满意度进行统一跟踪评估 进行分级管理 分级评估 2 订单管理 按订单状态分类筛选 安装进度一目了然 3 智能派单 根据客户位置
  • 64位机器源码安装遇到的问题,解决,一锅端

    1 如果是centos5会出现如下问题 checking host system type Invalid configuration x86 64 unknown linux gnu machine x86 64 unknown not
  • Hexo-零基础搭建个人博客(详解)

    Hexo零基础搭建个人博客 Hexo是一个基于 node js的快速生成静态博客的开源框架 支持 Markdown和大多数 Octopress 插件 一个命令即可部署到 Github页面 Giteee Heroku等 强大的APl 可无限扩
  • 数据库关闭四种方式

    数据库关闭四种方式 shutdown 参数 默认normal abort 模拟突然掉电 内存被清空 内存中的数据没有写入数据文件 事务被立即中断 没有提交也没有回滚 immediate 强制中断当前正在运行的所有事务 回滚这些事务 回滚完毕
  • c语言编写简易的自动售货机程序

    今天本来想做一个弹窗的可以输入有按钮点确定的自动售货机程序的 但是因为学校没教我是自学的找了一下午 不是教我如何创建的 就是代码各种报错的 我试了一下午都不行 只能放弃了 今天这串代码是根据我的c语言笔试 我们有上机考试的 的其中一道编程的
  • 二、量化选股

    文章目录 总体介绍 一 基本面选股 1 因子选股 判断方法 五个步骤 2 风格轮动 3 行业轮动 二 市场行为选股 1 资金流 2 动量反转 基本概念 1 行为金融学 2 阿尔法动量模型 3 一致预期 4 趋势追踪 基本概念 5 筹码选股
  • uniGUI用Grid++Report报表插件设计保存报表(For unigui ver:0.95.0.1045)

    uniGUI的0 95 0 1045版本提供了CallbackUrl 我们也可以用这个提供的回调网址来实现优秀的国产报表插件在IE Chorme FireFox中在线设计并保存报表到服务端的功能 界面效果如下 代码如下 unit Main
  • SpringBoot用线程池ThreadPoolExecutor处理百万级数据

    SpringBoot用线程池ThreadPoolExecutor处理百万级数据 更多优秀文章 请扫码关注个人微信公众号或搜索 程序猿小杨 添加 一 背景 使用JDK线程池ThreadPoolExecutor多线程异步执行批量插入 更新等操作