首页 > 其他分享 >线程池分批处理excel数据

线程池分批处理excel数据

时间:2023-04-17 09:44:32浏览次数:34  
标签:java excel list 线程 分批 import List public

一、场景

  在开发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; } }
复制代码

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

标签:java,excel,list,线程,分批,import,List,public
From: https://www.cnblogs.com/beyondzw/p/17324800.html

相关文章

  • Win32API之实现远程线程注入(九)
    什么是注入注入是一种在不知情或未经许可的情况下向其他进程中注入模块并试图执行它们的技术常见的注入方式有:远程线程注入、APC注入、消息钩子注入、注册表注入、导入表注入、输入法注入等等什么是远程线程注入远程线程注入是一种技术,可以将一个动态链接库(DLL)注入到另一个进......
  • C 语言版线程池
    一、初始线程池1.1何为线程池?我们先来打个比方,线程池就好像一个工具箱,我们每次需要拧螺丝的时候都要从工具箱里面取出一个螺丝刀来。有时候需要取出一个来拧,有时候螺丝多的时候需要多个人取出多个来拧,拧完自己的螺丝那么就会把螺丝刀再放回去,然后别人下次用的时候再取出来用。......
  • 线程
    1.轻量级锁(自旋锁)无等待队列,忙等待。场景:线程执行时间短,等待线程少。2.重量级锁有等待队列,通过操作系统调度。场景:线程执行时间长,等待线程多。  关键字valatile:......
  • C++实现多线程
    #include<iostream>#include<chrono>#include<thread>voidprintNumbers1(){for(inti=1;i<=10000;i++){std::cout<<"Thread1:"<<i<<std::endl;}}voidprintNumbers2(){for......
  • Java中创建线程的方式以及线程池创建的方式、推荐使用ThreadPoolExecutor以及示例
    场景Java中创建线程的方式有三种1、通过继承Thread类来创建线程定义一个线程类使其继承Thread类,并重写其中的run方法,run方法内部就是线程要完成的任务,因此run方法也被称为执行体,使用start方法来启动线程。2、通过实现Runanle接口来创建线程首先定义Runnable接口,并重写Runnable接口......
  • 在Excel中输入特殊字符   
    使用标准的计算机键盘你可以输入大约94种不同的字符,包括字母、数字和其它一些功能符号。但是我们在实际应用中会使用很多其它的字符,这些字符都不能通过标准的US键盘直接输入,例如标准字体Arial中就有大约200种不同的字符可以使用,包括英镑符号£,欧元符号€,版权符号©等。本文描述了......
  • 第5章 高效的多线程日志
    日志库介绍:一个日志库大体可分为前端(frontend)和后端(backend)两部分。前端是供应用程序使用的接口(API),并生成日志消息(logmessage);后端则负责把日志消息写到目的地(destination)。在多线程程序中,前端和后端都与单线程程序无甚区别,无非是每个线程有自己的前端,整个程序共用一个后端。但难点......
  • [vba]-Excel-VBA操作文件四大方法之四(转)
     四、利用API函数来处理文件通过前面三种方法的介绍,你是否已经觉得足够了?是的,前面的方法完全可以应付几乎所有的文件操作。但是为了普及一下API,展示一下API的魅力,最后向大家介绍一下如何利用API函数来处理文件。另一方面也是本人对API情有独钟,为她做一下广告,呵呵。大家......
  • [vba]-Excel-VBA操作文件四大方法之三(转)
    三、利用FileSystemObject对象来处理文件FileSystemObject对象模型,是微软提供的专门用来访问计算机文件系统的,具有大量的属性、方法和事件。其使用面向对象的“object.method”语法来处理文件夹和文件,使用起来十分方便(需Office2000以后版本)。FileSystemObject并不是VBA的一部......
  • [vba]-Excel-VBA操作文件四大方法之二(转)
    二、利用VBA文件处理语句来处理文件   VBA包含了许多用于文件操作的语句和函数,可以满足绝大多数情况下的文件操作要求。下面我们按照操作目的进行一一介绍。(一)文件处理   1.Name语句语法:NameoldpathnameAsnewpathname功能:重命名一个文件、目录、或文件夹,移动一......