zoukankan      html  css  js  c++  java
  • 线程池分批处理excel数据

    一、场景

      在开发excel处理数据时,因为数据库的卡顿,一次插入2000条数据速度可能需要1min左右,所以考虑使用线程池;每200个分组,有n组,就开(n+1)个线程去分批同时处理这些数据。

    二、依赖

    1. pom.xml

            <!--工具类hutool,java兵器库,用于读取excel-->
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>4.5.10</version>
            </dependency>    

    2. excel的表格只有一个字段就是keyword,示例如下:

    3. 数据库:t_keyword(只有一个字段keyword,并且加唯一索引)

    三、代码

    dao.java

    package com.bds.pool.ihg_fb;
    
    import org.nutz.dao.impl.NutDao;
    import org.nutz.dao.impl.SimpleDataSource;
    
    /**
     * @ClassName:         Dao.java
     * @Description:  
     * @author :         jack.Lu
     * @version :         V1.0  
     * @Date :             2019年7月11日 下午5:08:13 
     */
    public class Dao {
        
        public static NutDao getDao() {
            // 创建一个数据源
            SimpleDataSource dataSource = new SimpleDataSource();
            dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1/bds");
            dataSource.setUsername("root");
            dataSource.setPassword("root");
    
            // 创建一个NutDao实例,在真实项目中, NutDao通常由ioc托管, 使用注入的方式获得.
            NutDao dao = new NutDao(dataSource);
            return dao;
        }
    
    }

    dealExcel.java

    package com.bds.pool.ihg_fb;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.nutz.dao.impl.NutDao;
    
    /**
     * @ClassName:         DealExcel.java
     * @Description:  
     * @author :         jack.Lu
     * @version :         V1.0  
     * @Date :             2019年7月11日 下午2:18:48 
     */
    public class DealExcel implements Runnable{
        
        List<String> list;
        
        private String thread_name;
        
        private Boolean success=false;
        
        public DealExcel(String thread_name,List<String> list) {
            this.thread_name = thread_name;
            this.list=list;
        }
        
        public int deal() {
            List<KeyWord> list_k = new ArrayList<>();
            KeyWord k = new KeyWord();
            NutDao dao = Dao.getDao();
            for(String s : list) {
                k.setKeyword(s);
                try {
                    dao.insert(k);
                } catch (Exception e) {
                    System.out.println(s+">>>>>>>>>>>已经插入!");
                }
            }
            
            return list.size();
        }
    
        @Override
        public void run() {
            System.out.println(this.thread_name+"***********"+Thread.currentThread().getName()+"开始处理....");
            int deal = this.deal();
            success = true;
            System.out.println(this.thread_name+"***********"+Thread.currentThread().getName()+"处理完成"+deal+"条数据");
        }
    
        public Boolean getSuccess() {
            return success;
        }
    
        public String getThread_name() {
            return thread_name;
        }
        
        
        
    }

    KeyWord.java

    package com.bds.pool.ihg_fb;
    
    import org.nutz.dao.entity.annotation.Column;
    import org.nutz.dao.entity.annotation.Table;
    
    /**
     * @ClassName:         KeyWord.java
     * @Description:  
     * @author :         jack.Lu
     * @version :         V1.0  
     * @Date :             2019年7月11日 下午5:09:54 
     */
    @Table("t_keyword")
    public class KeyWord {
        @Column
        private String keyword;
    
        public String getKeyword() {
            return keyword;
        }
    
        public void setKeyword(String keyword) {
            this.keyword = keyword;
        }
        
    
    }

    PoolThread.java

    package com.bds.pool.ihg_fb;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    
    import cn.hutool.core.io.FileUtil;
    import cn.hutool.poi.excel.ExcelReader;
    import cn.hutool.poi.excel.ExcelUtil;
    
    /**
     * @ClassName:         PoolThread.java
     * @Description:      开启线程池
     * @author :         jack.Lu
     * @version :         V1.0  
     * @Date :             2019年7月11日 下午2:18:35 
     */
    public class PoolThread {
        /**
       *程序的入口
       */
    public static void main(String args[])throws Exception{ readExcel(); } /** * 1.读取excel * 2.对excel进行200分段 * 3.开启线程池 * @param args */ public static void readExcel(){ //1.读取excel ExcelReader excelReader = ExcelUtil.getReader(FileUtil.file("C:\Users\admin\Desktop\新建文件夹\XHS 笔记需求 0709-03.xlsx")); List<Map<String,Object>> read = excelReader.readAll(); PoolThread pl = new PoolThread(); List<List<String>> excelByRead = pl.getExcelByRead(read);//500条数据,每200一条,共3组 //要开启的线程数//3组 int size = excelByRead.size(); ExecutorService pool = Executors.newFixedThreadPool(size+1); List<DealExcel> task_list = new ArrayList<DealExcel>(); for (int i = 0; i < size; i++) { List<String> list = excelByRead.get(i); DealExcel dx = new DealExcel(i+"-",list); task_list.add(dx); pool.execute(dx); } //结束线程池 pool.shutdown(); while(true) { if(pool.isTerminated()) { break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } String s = ""; for(DealExcel d : task_list) { s= s+d.getThread_name()+":"+(d.getSuccess()?"成功":"失败")+";"; } System.out.println("----------------------------------------------"); System.out.println(s); } /** * 以200为临界点 每200个放入一个String数组中,再放入List 集合中 * @param read * @return */ private List<List<String>> getExcelByRead(List<Map<String,Object>> read) { List<List<String>> list_list = new ArrayList<>(); int size = read.size(); int group = 200; int num = size/group; if(size%group!=0) {//说明不是整数101-》1+1=2 num = num +1; } System.out.println("准备创建几个数组就是开启多少线程:"+num); //开始遍历excel int temp = 0; for (int j = 1; j <= num; j++) { List<String> list = new ArrayList<>(); for (int i = temp; i < size; i++) { Map<String, Object> map = read.get(i); String keyword = map.get("keyword")+""; list.add(keyword); if ((i+1)%group==0) { temp=i+1; break; } } System.out.println("*****已经加入集合"+j+"次"); list_list.add(list); } System.out.println("########################添加结束##################################"); return list_list; } }

     学习总结:多种线程池的使用区别是他们的参数不同使用场景不同,在学习线程池的时候,到网上搜索所有的案例,但是发现全部都是分析线程池的区别,解剖源码,开始分析他们的体系,要么就是文章全部都是一样的东西,重复论述,巴拉巴拉。。。确实没有一个使用场景可以让好好参考,于是自己硬是想了一个场景,不知道效果如何但是确实联系了第一次写线程池来处理业务。希望有错可以给我及时指出来。谢谢!

  • 相关阅读:
    系统吞吐量、TPS(QPS)、用户并发量、性能測试概念和公式
    限流实现与解决方案
    mysql事务,select for update,及数据的一致性处理
    **MySQL锁机制与用法分析**
    死锁的排查
    系统中异常的设计与处理
    Spring如何处理线程并发问题
    ThreadLocal作用、场景、原理
    Database Administration Statements
    mybatis 无法自动补全,没有获得dtd文件
  • 原文地址:https://www.cnblogs.com/luruihua/p/11171547.html
Copyright © 2011-2022 走看看