前言:
眼前大家对“java批量导入千万级excel”都比较关切,朋友们都想要学习一些“java批量导入千万级excel”的相关文章。那么小编同时在网摘上搜集了一些有关“java批量导入千万级excel””的相关文章,希望各位老铁们能喜欢,兄弟们快快来学习一下吧!线程池优化导入Excel功能核心代码如下:
StopWatch stopWatch = new StopWatch("任务"); stopWatch.start("处理数据"); int totalSize = dataList.size(); LOG.info("{},线程开始, 条数:{}", totalSize); List<Future> fuList = new ArrayList<>(); /** * 设置线程池: * 线程池核心线程数 * 线程池最大线程数 * 空闲线程存活时间(过期回收) * LinkedBlockingQueue: 阻塞队列 * 拒绝处理策略: * ThreadPoolExecutor.AbortPolicy():被拒绝后抛出RejectedExecutionException异常 * ThreadPoolExecutor.CallerRunsPolicy():被拒绝后给调用线程池的线程处理 * ThreadPoolExecutor.DiscardOldestPolicy():被拒绝后放弃队列中最旧的未处理的任务 * ThreadPoolExecutor.DiscardPolicy():被拒绝后放弃被拒绝的任务(当前新添加的任务) * */ ThreadPoolExecutor pool = new ThreadPoolExecutor( 8, 17, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new ThreadPoolExecutor.DiscardOldestPolicy()); int leftCount = totalSize % batchSize; int last = 0; for (int i = 0; i < totalSize / batchSize; i++) { int start = i * batchSize; last = start + batchSize; final List subList = dataList.subList(start, last); Future<?> f = pool.submit(new Runnable() { @Override public void run() { doBusiness(subList,user, poetryTypeService, authorService, poetryService); } }); fuList.add(f); } final List leftList = dataList.subList(last, last + leftCount); if (leftList.size() > 0) { LOG.info("left data size:{}", leftList.size()); Future<?> f = pool.submit(new Runnable() { @Override public void run() { //你的业务逻辑 doBusiness(leftList,user, poetryTypeService, authorService, poetryService); } }); fuList.add(f); } for (Future fu : fuList) { fu.get(); } pool.shutdown(); stopWatch.stop(); LOG.info("导入成功,总条数:{},{}", totalSize, stopWatch.prettyPrint());
调用方式:
ImportTask importTask = new ImportTaskMngImpl(list, user, poetryTypeService, authorService, poetryService); importTask.exec();
使用easypoi实现导入Excel功能:
List<PoetryDTO> list =ExcelImportUtil.importExcel(file.getInputStream(),PoetryDTO.class, params);
在使用线程池之前,需要先了解线程池!
创建线程池有俩种方式:通过Executors类提供的方法和通过ThreadPoolExecutor类自定义。
一、通过Executors类提供的方法
Executors类有四种线程池,分别是:
1.创建一个可缓存的线程池newCachedThreadPool
2.创建一个固定大小的线程池newFixedThreadPool
3.创建一个周期性的线程池newScheduledThreadPool
4.创建一个单线程的线程池newSingleThreadExecutor
二、通过ThreadPoolExecutor类自定义
ThreadPoolExecutor类提供了4种构造方法,可根据需要来自定义一个线程池。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { // 省略... }
参数说明:
1.corePoolSize:核心线程数,线程池中始终存活的线程数。
2.maximumPoolSize: 最大线程数,线程池中允许的最大线程数。
3.keepAliveTime: 存活时间,线程没有任务执行时最多保持多久时间会终止。
4.unit: 单位,参数keepAliveTime的时间单位,7种可选。
参数
描述
TimeUnit.DAYS
天
TimeUnit.HOURS
小时
TimeUnit.MINUTES
分
TimeUnit.SECONDS
秒
TimeUnit.MILLISECONDS
毫秒
TimeUnit.MICROSECONDS
微妙
TimeUnit.NANOSECONDS
纳秒
5.workQueue: 一个阻塞队列,用来存储等待执行的任务,均为线程安全,7种可选。
参数
描述
ArrayBlockingQueue
一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue
一个由链表结构组成的有界阻塞队列。
SynchronousQueue
一个不存储元素的阻塞队列,即直接提交给线程不保持它们。
PriorityBlockingQueue
一个支持优先级排序的无界阻塞队列。
DelayQueue
一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素。
LinkedTransferQueue
一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似,还含有非阻塞方法。
LinkedBlockingDeque
一个由链表结构组成的双向阻塞队列。
较常用的是LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关。
6.threadFactory: 线程工厂,主要用来创建线程,默及正常优先级、非守护线程。
7.handler:拒绝策略,拒绝处理任务时的策略,4种可选,默认为AbortPolicy。
参数
描述
AbortPolicy
拒绝并抛出异常。
CallerRunsPolicy
重试提交当前的任务,即再次调用运行该任务的execute()方法。
DiscardOldestPolicy
抛弃队列头部(最旧)的一个任务,并执行当前任务。
DiscardPolicy
抛弃当前任务。
线程池的执行规则
当线程数小于核心线程数时,创建线程;
当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列;
当线程数大于等于核心线程数,且任务队列已满:若线程数小于最大线程数,创建线程,若线程数等于最大线程数,抛出异常,拒绝任务。
建议使用自定义类ThreadPoolExecutor类来创建线程池!
标签: #java批量导入千万级excel