Java多线程读取图片内容并返回
1. ExecutorService线程池
ExecutorService线程池,并可根据系统核数动态确定线程池最大数;
// 最大、最小线程数一致,均为系统核数*10+1;链表阻塞对列最多提交200个任务,这个值的设置很关键
private static int workerNum = Runtime.getRuntime().availableProcessors() * 10 + 1;
private static ExecutorService cachedThreadPool = new ThreadPoolExecutor(workerNum, workerNum, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(200), new ThreadPoolExecutor.CallerRunsPolicy());
2. 效率截图
亲测可达到150张照片耗时10ms,照片大小40K+;
3. 源码
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/*************************************
* Class Name: TestUploadImg
* Description:〈测试多线程上传照片〉
* @since 1.0.0
************************************/
@Slf4j
public class TestUploadImg {
// 最大、最小线程数一致,均为系统核数*10+1;链表阻塞对列最多提交200个任务
private static int workerNum = Runtime.getRuntime().availableProcessors() * 10 + 1;
private static ExecutorService cachedThreadPool = new ThreadPoolExecutor(workerNum, workerNum, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(200), new ThreadPoolExecutor.CallerRunsPolicy());
public static <T> Future<T> submit(Callable<T> callable) {
try {
return cachedThreadPool.submit(callable);
} catch (Exception e) {
log.error("upload image exception ", e);
}
return null;
}
public static void shutdown() {
try {
if (cachedThreadPool.isShutdown()) {
return;
}
cachedThreadPool.shutdown();
} catch (Exception e) {
log.error("shutdown thread pool fail, ", e);
}
}
public static void main(String[] args) {
log.info("systemAvailableProcessors: {}", workerNum);
String imgPathDir = "F:\\test\\images\\";
List<String> imageNameList = getImageFileNames(imgPathDir);
log.info("imageSize: {}", imageNameList.size());
int total = imageNameList.size(); // 照片总数
// 文件读取,每次读取150张图片,最后一次剩几张读取几张
int fromIndex = 0, endIndex = 0;
int batchNum = 150;
do {
endIndex += batchNum;
endIndex = endIndex > total ? total : endIndex;
log.info("fromIndex: {}, endIndex: {}", fromIndex, endIndex);
List<Image> imageList = readImageByPath(imgPathDir, imageNameList.subList(fromIndex, endIndex));
fromIndex += batchNum;
if (imageList.isEmpty()) {
log.warn("fail to read any image, file: {}", imgPathDir);
continue;
} else {
log.info("read image success, image count: {}", imageList.size());
}
} while (endIndex < total);
log.info("-------------endl----------------");
}
/**
* 获取文件夹下所有的jpg
*
* @param path 路径
* @throws Exception
*/
public static List<String> getImageFileNames(String path) {
List<String> nameList = new ArrayList<>();
//目标集合fileList
File file = new File(path);
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File fileIndex : files) {
if (fileIndex.getName().endsWith(".jpg")) {
nameList.add(fileIndex.getName());
}
}
} else {
if (file.getName().endsWith(".jpg")) {
nameList.add(file.getName());
}
}
return nameList;
}
/**
* 根据图片路径读取图片并封装返回
*
* @param imgPathDir 图片目录
* @param imageNameList 图片名称列表
* @return
*/
public static List<Image> readImageByPath(String imgPathDir, List<String> imageNameList) {
List<Image> imageList = new ArrayList<>();
List<Future<Image>> futureList = new ArrayList<>();
for (int i = 0; i < imageNameList.size(); i++) {
String fileName = imageNameList.get(i);
Future<Image> imageFuture = TestUploadImg.submit(() -> {
return parseImage(imgPathDir, fileName);
});
futureList.add(imageFuture);
}
for (Future<Image> future : futureList) {
try {
if (future.get() != null) {
imageList.add(future.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return imageList;
}
private static Image parseImage(String filePath, String imageName) {
String fileName = filePath + imageName;
if (StringUtils.isEmpty(fileName)) {
return null;
}
byte[] data = null;
try (FileInputStream inputStream = new FileInputStream(fileName)) {
data = new byte[inputStream.available()];
inputStream.read(data);
} catch (FileNotFoundException e) {
log.error("imageName: {}, file NotExists...", fileName);
} catch (IOException e) {
e.printStackTrace();
}
Image image = new Image();
image.setImageName(imageName);
if (data != null) {
image.setContent(data);
return image;
} else {
log.error("readImage {} fail...", filePath);
}
return null;
}
static class Image {
/**
* 照片名称
*/
String imageName;
/**
* 照片内容
*/
byte[] content;
public String getImageName() {
return imageName;
}
public void setImageName(String imageName) {
this.imageName = imageName;
}
public byte[] getContent() {
return content;
}
public void setContent(byte[] content) {
this.content = content;
}
}
}