package com.test.bo;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@Service
public class TestBo {
//创建一个线程放在后台执行一些批量操作类的业务
private static ExecutorService executor = Executors.newSingleThreadExecutor();
/**
* 批量导入
*
* @param uploadFile
* @param uploadFileName
* @throws FileNotFoundException
* @throws IOException
*/
public void uploadFile(final MultipartFile uploadFile, final String uploadFileName) throws Exception {
final String[][] result = PoiUtil.getData(uploadFile, uploadFileName, 0, 1);// 0:第一个sheet // 1:从第二行开始获取数据,第一行为标题
executor.execute(new Runnable() {
@Override
public void run() {
try {
uploadFile(uploadFileName, result);
} catch (Exception e) {
e.printStackTrace();
logger.error("批量导入异常");
}
}
});
}
/**
* 解析excel文件
*
* @param uploadFileName
* @param result
*/
public void uploadFile(final String uploadFileName, final String[][] result) {
//.....业务逻辑处理,省略
}
}
PoiUtil解析导入的Excel文件:
package com.test.common.util;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class PoiUtil {
/**
* 读取Excel的内容,第一维数组存储的是一行中格列的值,二维数组存储的是多少个行
*
* @param file
* 读取数据的源Excel
* @param ignoreRows
* 读取数据忽略的行数,比喻行头不需要读入 忽略的行数为1
* @return 读出的Excel中数据的内容
* @throws FileNotFoundException
* @throws IOException
*/
public static String[][] getData(MultipartFile file, String uploadFileName, int sheetNum, int rowNum)
throws FileNotFoundException, IOException {
List<String[]> result = new ArrayList<String[]>();
int rowSize = 0;
InputStream in = file.getInputStream();
Workbook wb = null;
if (isExcel2003(uploadFileName)){
wb = new HSSFWorkbook(in);
}else{
wb = new XSSFWorkbook(in);
}
Cell cell = null;
Sheet st = wb.getSheetAt(sheetNum);
// 第一行为标题,不取
for (int rowIndex = rowNum; rowIndex <= st.getLastRowNum(); rowIndex++) {
Row row = st.getRow(rowIndex);
if (row == null) {
continue;
}
int tempRowSize = row.getLastCellNum() + 1;
if (tempRowSize > rowSize) {
rowSize = tempRowSize;
}
String[] values = new String[rowSize];
Arrays.fill(values, "");
boolean hasValue = false;
for (short columnIndex = 0; columnIndex <= row.getLastCellNum(); columnIndex++) {
String value = "";
cell = row.getCell(columnIndex);
if (cell != null) {
//cell.setEncoding(HSSFCell.ENCODING_UTF_16);
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
value = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_NUMERIC:
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = cell.getDateCellValue();
if (date != null) {
value = new SimpleDateFormat("yyyy-MM-dd").format(date);
} else {
value = "";
}
} else {
value = formatCnt(BigDecimal.valueOf(cell.getNumericCellValue()).toString());
}
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
value = String.valueOf(cell.getBooleanCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK:
value = "";
break;
case HSSFCell.CELL_TYPE_ERROR:
value = "";
break;
default:
value = "";
}
}
// if (columnIndex == 0 && value.trim().equals("")) {
// break;
// }
values[columnIndex] = value.trim();
hasValue = true;
}
if (hasValue) {
result.add(values);
}
}
in.close();
String[][] returnArray = new String[result.size()][rowSize];
for (int i = 0; i < returnArray.length; i++) {
returnArray[i] = (String[]) result.get(i);
}
return returnArray;
}
public static boolean isExcel2003(String filePath){
return filePath.matches("^.+\\.(?i)(xls)$");
}
public static boolean isExcel2007(String filePath){
return filePath.matches("^.+\\.(?i)(xlsx)$");
}
public static String formatCnt(String cnt){
String[] arrayStr = cnt.split("\\.");
if(arrayStr.length>1 && Double.parseDouble("0."+arrayStr[1]) == 0){
return arrayStr[0];
}else{
return cnt;
}
}
}
分享到:
相关推荐
为了解决同步和性能的问题,我们使用ExecutorService创建了一个单线程的线程池(通过Executors.newSingleThreadExecutor())。这样,所有提交到线程池的任务都会按照提交的顺序在单个线程中依次执行,从而确保对临界...
Java作为多线程编程的强大语言,提供了多种创建线程的方法,其中一种是通过创建线程类来实现。本文将深入探讨如何创建线程类以及如何进行线程管理,帮助你轻松掌握这一核心技能。 首先,我们来看看如何在Java中创建...
本篇文章将深入探讨Java中创建线程的几种方法,以及如何通过示例源代码进行学习。 首先,Java提供了两种主要的方式来创建线程: 1. **继承Thread类**:创建一个新的类,该类继承自`Thread`类,并重写`run()`方法。...
在Java编程语言中,创建线程有两种主要方式:继承`Thread`类和实现`Runnable`接口。由于Java的单继承特性,当一个类需要继承其他类时,就不能再直接继承`Thread`,这时实现`Runnable`接口就成为创建线程的优选方案。...
本文将深入探讨Java多线程中的关键知识点,包括创建线程、主线程、线程优先级、线程组、线程同步以及线程间的通信。 1. **创建线程** 在Java中,可以通过两种方式创建线程:继承`Thread`类或实现`Runnable`接口。...
Java线程池是一种高效管理线程的机制,它允许开发者预先创建一定数量的线程,然后根据需求将任务提交到线程池中进行执行。线程池的核心在于它能够有效地控制运行的线程数量,避免因为频繁创建和销毁线程而产生的性能...
本篇文章将深入探讨线程的挂起与恢复,以及如何创建线程,并简要提及线程间的消息传递。 1. 线程的创建 在大多数编程语言中,如Java、C#或Python,都有内置的多线程支持。在Java中,可以使用`Thread`类的子类化或...
Java 使用 ExecutorService 来停止线程服务 Java 中的 ExecutorService 是一个非常强大的线程池管理工具,它提供了多种方式来停止线程服务。今天,我们将详细介绍如何使用 ExecutorService 来停止线程服务。 首先...
在上面的代码中,我们创建了一个线程池配置类,使用 @Bean 注解创建了一个线程池实例,该实例具有 5 个核心线程,10 个最大线程,闲置线程存活 60 秒,使用 ArrayBlockingQueue 作为任务队列。 总结 在 Spring ...
创建线程有多种方式: - **继承Thread类**:如前所述,自定义一个Thread子类并重写`run()`方法。 - **实现Runnable接口**:创建一个实现了Runnable接口的类,然后将其实例传递给Thread的构造器,同样可以启动新...
创建线程是提高程序效率和响应性的重要手段。本示例将深入探讨如何在Java中创建线程,以及相关的概念和技术。 1. **线程的概念**: 线程是操作系统分配CPU时间的基本单位,它在进程内部运行。一个进程可以拥有多个...
3. 使用ExecutorService创建线程: ExecutorService是Java并发包(java.util.concurrent)的一部分,提供了更高级的线程管理功能。你可以创建ExecutorService实例,然后通过submit()或execute()方法提交Runnable或...
在Java编程语言中,创建线程是实现多任务并发执行的关键技术。线程允许程序同时执行多个不同的操作,极大地提高了程序的效率和响应性。Java提供了两种主要的方式来创建线程:通过实现Runnable接口和继承Thread类。 ...
在Android开发中,创建线程是常见的操作,用于在后台执行耗时任务,避免阻塞主线程导致应用无响应(ANR)。标题“创建线程实现App.zip”和描述“android创建线程”都指向了这个核心主题。下面将详细讨论Android中...
在Java编程语言中,创建线程是实现多任务并发执行的关键。标题提到的"创建线程的两种方法"指的是使用`Thread`类和实现`Runnable`接口。这两种方法都是Java中实现多线程的重要手段,各有特点和适用场景。下面我们将...
本文将深入探讨如何利用`Thread`来创建线程,以及相关的重要知识点。 1. **线程的创建方式** Java提供了两种创建线程的方法: - **继承Thread类**:创建一个新的类,该类继承自`Thread`类,并重写`run()`方法。...
SimpleAsyncTaskExecutor线程池的核心特性是每次调用异步方法时都会创建一个新线程,虽然可以设置最大并发线程数量,但每次调用还是会为每个任务创建线程,这在频繁调用异步方法的场景下显然不是最优的解决方案。...
ExecutorService提供了一种管理线程的方式,允许我们创建、管理和控制线程执行任务,从而提高系统的效率和可维护性。线程池的使用能够有效避免频繁创建和销毁线程带来的性能开销,同时还能通过任务队列来限制系统...
本篇将深入探讨标题"8种常用创建线程的方法thread.zip"中提到的八种主要的Java线程创建方法,帮助开发者更好地理解和掌握这一核心概念。 1. 继承Thread类 Java中的`Thread`类是所有线程的基类,我们可以通过创建`...
当我们创建一个`ExecutorService`实例并提交任务时,我们可以通过调用`shutdown()`方法来关闭线程池。然而,标题指出"ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭",这意味着`shutdown()`方法...