springboot多线程等待所有结果返回
场景:
比如我们需要同时上传多个文件,我们可以通过多线程的处理每一个文件的上传来提升效率
1. 配置多线程
package com.ruoyi.file.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @ClassName UploadThreadPoolConfig
* @Description 文件上传的线程池
* @Author
* @Date 9:27 2022/10/21
* @Version 1.0
**/
@Configuration
public class UploadThreadPoolConfig {
private static final Integer CORE_POOL_SIZE = 5;
private static final Integer MAX_POOL_SIZE = 10;
private static final Integer TASK_QUEUE_CAPACITY = 5;
private static final Integer TASK_KEEP_ALIVE_TIME = 60;
@Bean(name = "uploadThreadPoolTaskExecutor")
public ThreadPoolTaskExecutor uploadThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(TASK_QUEUE_CAPACITY);
executor.setThreadNamePrefix("uploadThreadPoolTaskExecutor");
// 设置线程保持活跃的时间(默认:60)
executor.setKeepAliveSeconds(TASK_KEEP_ALIVE_TIME);
// 设置任务拒绝策略 通过主线程知行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
2. controller层代码
通过CountDownLatch来实现等待所有线程统一返回结果
package com.ruoyi.file.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.file.service.ISysFileService;
import com.ruoyi.system.api.domain.SysFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* 文件请求处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/file")
public class SysFileController
{
private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
@Autowired
private ISysFileService sysFileService;
@Resource(name = "uploadThreadPoolTaskExecutor")
private ThreadPoolTaskExecutor uploadThreadPoolTaskExecutor;
/**
* 批量上传文件
*/
@PostMapping("/batchUpload")
public List<SysFile> batchUpload(MultipartFile[] files) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(files.length);
List<SysFile> sysFileList = new ArrayList<>();
for (MultipartFile file : files) {
SysFile sysFile = new SysFile();
sysFile.setName(file.getOriginalFilename());
// 处理上传文件线程
Thread uploadThread = new Thread(){
@Override
public void run() {
try {
// 上传文件返回路径
String url = sysFileService.uploadFile(file);
sysFile.setUrl(url);
sysFile.setCode(200);
sysFile.setMsg("上传成功");
} catch (Exception e) {
sysFile.setCode(500);
sysFile.setMsg("上传失败:"+e.getMessage());
} finally {
countDownLatch.countDown();
}
}
};
uploadThreadPoolTaskExecutor.submit(uploadThread);
sysFileList.add(sysFile);
}
countDownLatch.await();
return sysFileList;
}
}