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;
}
}
}
分享到:
相关推荐
1.newFixedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。`` 2.newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列...
3.如果队列满了, 则判断线程池是否已满, 如果没满, 创建线程执行任务 4.如果线程池满了, 按照拒绝策略对任务进行处理 JDK中提供了一个线程池工厂: Executors ,很多工厂方法, 可以创建多种线程池 1.单一线程池 ...
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 • 重用之前的线程 • 适合执行许多短期异步任务的程序。 • 调用 execute() 将重用以前构造的线程 • 如果没有...
(2)实现Runnable接口方式实现多线程:(3)实现callable方式:(比实现Runnable方式强大)(4)使用ExecutorService、Future(线程池):实现有返回结果的多线程:线程池方式代码说明:总结:就是4种线程的创建方式,...
一、背景 多线程能够在操作系统多核配置的基础上,更好的利用服务器多个...具体使用方式,创建一个类并继承Thread接口,然后实例化线程对象并调用start()方法启动线程,start方法是navite方法。代码如下 private stat
Java语言虽然内置了多线程支持,启动一个新线程非常方便,但是,创建线程需要操作系统资源(线程资源,栈空间等),频繁创建和销毁大量线程需要消耗大量时间。 而线程池内部维护了若干个线程,没有任务的时候,这些...
Executor: 一个接口,其定义了一个接收Runnable对象的方法...new Thread(new RunnableTask())).start(),但在Executor中,可以使用Executor而不用显示地创建线程:executor.execute(new RunnableTask()); // 异步执行
主要介绍了Java 线程池ExecutorService详解及实例代码的相关资料,线程池减少在创建和销毁线程上所花的时间以及系统资源的开销.如果不使用线程池,有可能造成系统创建大量线程而导致消耗系统内存以及”过度切换
线程池:了解Java中的线程池概念,如ExecutorService和ThreadPoolExecutor,它们用于管理线程的创建、销毁和复用,以提高系统性能。 并发工具类:掌握Java并发包java.util.concurrent中提供的各种工具类,如...
创建线程池ExecutorService和资源 * 7.创建MyBaseadapter带参构造函数(Context context) * 8.创建ViewHolder对象用于存储那些Item内部的View的直接引用 * 9.getView()中判断convertView是否为空,防止过多填充...
首先,我们定义了一个URL地址和一个超时时间(TIMEOUT),然后使用ExecutorService创建了一个线程池,该线程池包含两个线程。接下来,我们通过调用executor.submit()方法提交了两个任务,分别对应GET和POST两种HTTP...
start()方法会创建新的线程并启动该线程,所以该方法会调用其他native方法,而run()方法就是: 正常的Java方法调用,即在原来的线程中执行java代码。 Java中Runnable和Callable的区别 Runnable和Callable都代表要...
使用Java的ExecutorService类创建了一个固定大小的线程池,并将任务安排到线程池中执行。 通过调用`scheduleTask()`方法,可以指定要执行的任务、延迟时间和延迟时间单位。 任务将在指定的延迟时间后被安排到线程池...
线程池是可以容纳多个线程的容器,程序可以从线程池获取线程来完成目标代码,同时也可以将线程归还给线程池,省去了创建线程和销毁线程这样非常繁琐的操作。 2、线程池的使用 public static ExecutorService ...
我什至看过匿名的AyncTask实现:( TaskExecutor将所有异步活动整合到一个ExecutorService中,可以通过一个唯一查询的服务在所有Activity应用程序中访问它。不再需要匿名线程,不必在一个Activity中启动线程,也不必...
多线程消息此解决方案使用Files.lines(Paths.get(path))创建一行行,这些行分别包装在Runnable处理器类Consumer并传递给ExecutionSevice例如FixedOrderedExecutor实例)以及消息ID来执行。 执行程序类...
6.1.3 无限制创建线程的不足95 6.2 Executor框架96 6.2.1 示例:基于Executor的Web服务器97 6.2.2 执行策略98 6.2.3 线程池98 6.2.4 Executor的生命周期99 6.2.5 延迟任务与周期任务101 6.3 找出可利用的...
ExecutorService基于池化的线程来执行用户提交的任务,通常可以简单的通过Executors提供的工厂方法来创建ThreadPoolExecutor实例。 线程池解决的两个问题:1)线程池通过减少每次做任务的时候产生的性能消耗来...
在main方法中,创建了一个BankAccountManager对象和ExecutorService线程池,并初始化了1000个账户和10个线程。然后循环遍历每个账户,将每个账户提交给线程池执行转账操作。在transfer方法中,获取两个账户对象和...
这段代码实现了一个简单的线程池ExecutorService,其中使用了Java的匿名内部类。在类的构造方法中,首先创建了一个固定大小为5的线程池。然后通过循环提交了10个任务到线程池中执行。每个任务都是一个匿名内部类实现...