多線程解決大數據批量導出問題(demo)

1.首先從網上找一個到工具類,我這里是ExcelUtils,如下

?

package com.org.util;import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;public class ExcelUtils {// 導出 Excelpublic static Integer exportExcel(SXSSFSheet sheet, List<Object> dataList, Integer currentRow) throws IntrospectionException, InvocationTargetException, IllegalAccessException {if (null == dataList || dataList.size() == 0) {return -1;}// 反射Object object =  dataList.get(0);Class<?> clazz = object.getClass();Field[] fields = clazz.getDeclaredFields();//如果是第一行,創建表頭if (0 == currentRow) {SXSSFRow row = sheet.createRow(currentRow++);for (int i = 0; i < fields.length; i++) {SXSSFCell cell = row.createCell(i);cell.setCellValue(fields[i].getName());//設置單元格的值為字段名}}//填充數據for (Object item : dataList) {SXSSFRow row = sheet.createRow(currentRow++);for (int i = 0; i < fields.length; i++) {SXSSFCell cell = row.createCell(i);// get MethodPropertyDescriptor propertyDescriptor = new PropertyDescriptor(fields[i].getName(), item.getClass());Method getMethod = propertyDescriptor.getReadMethod();// valueObject value = getMethod.invoke(item);cell.setCellValue(value.toString());//設置單元格的值為字段值的字符表現形式}}return currentRow;}
}

public class DataBaseTest {private static final ConcurrentHashMap<Integer, FutureTask<Integer>> taskList = new ConcurrentHashMap<>();public static void main(String[] args) throws ExecutionException, InterruptedException, IOException {// mapperSqlSession sqlSession = MyBatisUtils.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 查出總數int totalNum = userMapper.getTotalNum();// 10個線程數int taskNum = 10;// 總數據量int avg = (int) Math.floor(totalNum / taskNum);int[] startRows = calcStartRowIndex(totalNum, taskNum);// ExcelSXSSFWorkbook workbook = new SXSSFWorkbook();SXSSFSheet sheet = workbook.createSheet();for (int i = 0; i < taskNum; i++) {final int temp = i;FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {System.out.println("開始執行任務" + temp + "...");HashMap<String, Object> map = new HashMap<>();List<User> userList = null;// 分頁查詢if (temp == taskNum - 1) {// 如果是最后一個線程map.put("startIndex", startRows[temp] - 1); //9001-1// 計算起始位置到最后的數量map.put("num", totalNum - startRows[temp] + 1); //10001-9001+1userList = userMapper.getListByPage(map);} else {//如果是前九個線程的花執行下面的操作map.put("startIndex", startRows[temp] == 0 ? 0 : startRows[temp] - 1);map.put("num", avg);userList = userMapper.getListByPage(map);}List<Object> dataList = new ArrayList<>();for (User user : userList) {dataList.add(user);}Integer currentRow = ExcelUtils.exportExcel(sheet, dataList, startRows[temp]);System.out.println("任務" + temp + "執行結束...");return currentRow;}});taskList.putIfAbsent(i, futureTask);}int taskIndex = 0;while (true) {FutureTask<Integer> futureTask = taskList.remove(taskIndex++);if (null != futureTask) {futureTask.run();Integer currentRow = futureTask.get();}if (taskList.size() == 0) {// 寫入磁盤System.out.println("開始寫入磁盤");FileOutputStream fileOutputStream = new FileOutputStream(new File("c:\\users\\che\\desktop\\test01.xlsx"));workbook.write(fileOutputStream);break;}}}// 計算每一趟起始位置public static int[] calcStartRowIndex(int totalNum, int taskNum) {int[] resultArray = new int[taskNum];int avg = (int) Math.floor(totalNum / taskNum);for (int i = 0; i < taskNum; i++) {if (i == 0) {resultArray[i] = i * avg;} else {resultArray[i] = i * avg + 1;}}return resultArray;}public static void addDataSource() {SqlSession sqlSession = MyBatisUtils.getSqlSession();try {UserMapper userMapper = sqlSession.getMapper(UserMapper.class);for (int i = 0; i < 10000; i++) {User user = new User("T" + i, i, "男", "10086", "qwe@qq.com", "日本京都");System.out.println(user);userMapper.addUser(user);}sqlSession.commit();} catch (Exception e) {e.printStackTrace();} finally {
//            sqlSession.close();}}
}

具體代碼示例包在次處

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/162513.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/162513.shtml
英文地址,請注明出處:http://en.pswp.cn/news/162513.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Navicat 技術指引 | GaussDB 數據查看器

Navicat Premium&#xff08;16.2.8 Windows版或以上&#xff09; 已支持對GaussDB 主備版的管理和開發功能。它不僅具備輕松、便捷的可視化數據查看和編輯功能&#xff0c;還提供強大的高階功能&#xff08;如模型、結構同步、協同合作、數據遷移等&#xff09;&#xff0c;這…

讀論文模板

文章簡介 文章標題&#xff1a;文章鏈接作者單位&#xff1a;文章來源&#xff1a;會議視頻ppt1.他人代碼 2.作者代碼 文章思路 文章總結 1.解決問題 2.使用方法 3.文章不足

解釋器模式 (Interpreter Pattern)

定義 解釋器模式&#xff08;Interpreter Pattern&#xff09;是一種行為型設計模式&#xff0c;用于定義一種語言的語法表示&#xff0c;并提供一個解釋器來處理這種語法。這種模式用于實現語言解釋器&#xff0c;通常用于專業領域或復雜文本處理中。在解釋器模式中&#xff…

220V轉12V固定輸出12V非隔離芯片WT5106WT5105

220V轉12V固定輸出12V非隔離芯片WT5106WT5105 今天給大家介紹一款實用芯片&#xff0c;WT5106。它是一款高效率高精度的非隔離降壓開關電源恒壓控制驅動芯片。 WT5106適用于85VAC~265VAC全范圍輸入電壓的非隔離Buck、Buckboost拓撲結構&#xff0c;小家電、電機驅動、繼電器驅…

量子計算爭霸戰加碼?美國將撥款30億美元發展量子計算

&#xff08;圖片來源&#xff1a;網絡&#xff09; 美國眾議院科學、太空和技術委員會認為&#xff0c;如果不采取措施加速量子計算系統的發展&#xff0c;美國將落后于俄羅斯和中國。 因此&#xff0c;該小組的領導人——主席Frank Lucas&#xff08;共和黨&#xff09;和高…

云貝教育 |【PostgreSQL PGCA題目解析5】PostgresSQL是否能夠自動檢測到死鎖,然后退出其中一個事務?

考試科目&#xff1a;PGCA-E-090 考試題量&#xff1a;40 道單項選擇題、10 道多項選擇題&#xff08;每題 2 分&#xff09; 通過分數&#xff1a;60% 考試時間&#xff1a;60min 本文為云貝教育劉峰&#xff08;微信&#xff1a;yunbee_DBA&#xff09;原創&#xff0c;請…

基于 Modbus 的工業數據采集、控制(part 3)

Modbus 設備(利用 slave 模擬) Modbus 采集程序 client.c #include "client.h"modbus_t *ctx; key_t key_shm, key_msg; int shmid, msgid; struct shm *shm0; struct msgbuf msg0;void *collector(void *arg) {struct shm *p = (struct shm *)arg;while (1){sle…

瀏覽器事件循環原理 —— JS為何會阻礙渲染?

系列文章目錄 第一章 瀏覽器事件循環原理 —— 瀏覽器進程模型第二章 瀏覽器事件循環原理 —— 渲染主線程如何工作&#xff1f;第三章 瀏覽器事件循環原理 —— 何為異步&#xff1f; 文章目錄 系列文章目錄 文章目錄 前言 代碼解析 總結 前言 該文章作用于 “web前端大…

橋接模式 (Bridge Pattern)

定義&#xff1a; 橋接模式&#xff08;Bridge Pattern&#xff09;是一種結構型設計模式&#xff0c;用于將抽象部分與其實現部分分離&#xff0c;使它們可以獨立地變化。這種模式通過創建一個橋接接口&#xff0c;將抽象類和其實現類解耦&#xff0c;使得修改或擴展獨立的抽…

改進YOLOv5 | C3模塊改動篇 | 輕量化設計 |骨干引入動態卷積|CondConv

???YOLOv5實戰寶典--星級指南:從入門到精通,您不可錯過的技巧 ??-- 聚焦于YOLO的 最新版本, 對頸部網絡改進、添加局部注意力、增加檢測頭部,實測漲點 ?? 深入淺出YOLOv5:我的專業筆記與技術總結 ??-- YOLOv5輕松上手, 適用技術小白,文章代碼齊全,僅需 …

信號功率放大器的工作原理和特點是什么

信號功率放大器是一種電子設備&#xff0c;用于將輸入信號的功率進行放大&#xff0c;以達到所需的輸出功率水平。它在各個領域中都有廣泛的應用&#xff0c;包括音頻放大器、射頻放大器、激光功率放大器等。下面將詳細介紹信號功率放大器的工作原理和特點。 工作原理&#xff…

Git使用基礎總結(從小白到新手版)

(??? )&#xff0c;Hello我是祐言QAQ我的博客主頁&#xff1a;C/C語言&#xff0c;數據結構&#xff0c;Linux基礎&#xff0c;ARM開發板&#xff0c;網絡編程等領域UP&#x1f30d;快上&#x1f698;&#xff0c;一起學習&#xff0c;讓我們成為一個強大的攻城獅&#xff0…

只知道ECMAScript 2015(ES6),一篇匯總ECMAScript 2015~ECMAScript 2023新特性

前言 我們常說的ES6也就是ECMAScript 2015是在2015年6月發布的。這個版本引入了許多重要的語言特性和改進&#xff0c;對 JavaScript 進行了深刻的擴展和升級&#xff0c;ES6 是 JavaScript 語言的一個里程碑。所以有時也被稱為ES6。這是由于規范的發布年份與實際版本號之間的…

OpenAI“宮斗”新進展!Sam Altman將重返OpenAI擔任首席執行官 董事會成員改動

在經過激烈的五天討論和辯論之后&#xff0c;高調人工智能初創公司OpenAI宣布&#xff0c;其聯合創始人之一Sam Altman將回歸擔任首席執行官。這一決定是對上周Altman突然被解雇的回應&#xff0c;該決定引起了極大的關注和討論。 OpenAI表示&#xff0c;他們已經達成了與Altm…

德迅云安全-德迅衛士:保障您的主機安全

主機安全是指保證主機在數據存儲和處理的保密性、完整性、可用性&#xff0c;包括硬件、固件、系統軟件的自身安全&#xff0c;以及一系列附加的安全技術和安全管理措施。 為什么要主機安全&#xff1f; 服務器一旦被黑客入侵&#xff0c;個人和企業面臨以下安全風險&#xff…

張弛聲音變現課,如何為偶像劇配音?

在為偶像劇進行配音工作時&#xff0c;配音員應當捕捉劇中角色的年輕活力、浪漫的愛情故事以及輕快的生活節奏。偶像劇主要講述的是青春的愛戀、友誼和夢想追求&#xff0c;因此配音需要傳遞出劇中的真誠和活潑。為偶像劇配音可以考慮以下幾點建議&#xff1a; 鮮明活潑的聲音 …

如何判斷交流回饋老化測試負載是否合格?

交流回饋老化測試負載是用于模擬實際工作環境中設備運行狀態的測試工具&#xff0c;主要用于檢測設備的耐久性和穩定性。 負載性能&#xff1a;需要檢查負載的性能是否符合設計要求&#xff0c;這包括負載的功率、電流、電壓等參數是否在規定的范圍內&#xff0c;以及負載的工作…

【AI】行業消息精選和分析(11月23日)

今日動態 1、Sam Altman 重掌 CEO&#xff0c;OpenAI 權力斗爭正式「落幕」 2、重磅好消息&#xff1a;語音 ChatGPT 現已向全用戶開放 3、NVIDIA 與基因泰克合作&#xff0c;利用生成式 AI 加速藥物發現 4、 英偉達Q3營收同比增長206%至181億美元 黃仁勛&#xff1a;生成式AI時…

Zoho Bigin和標準版CRM有什么區別?

Zoho Bigin是Zoho公司推出的一款針對小微企業設計的CRM系統&#xff0c;它與Zoho CRM一脈相承&#xff0c;但更加輕量級&#xff0c;快速幫助小微企業實現數字化銷售。下面來說說&#xff0c;Zoho Bigin是什么&#xff1f;它適合哪些企業&#xff1f; 什么是Zoho Bigin&#x…

【c語言】重溫一下動態內存,int數組過大會造成棧錯誤

項目場景&#xff1a; 項目場景&#xff1a;互助群同學在刷題的過程中&#xff0c;遇到的一個題目&#xff0c;需要申請一個很大數組&#xff0c;于是這個同學就寫了int[1000000],其實這樣寫也沒有錯&#xff0c;可是運行后卻顯示棧錯誤。于是就找到我來請教&#xff0c;我想就…