配置线程池
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* Excel任务执行器
*
*/
@Configuration
@ComponentScan("com.schedule.application.task") //异步扫描的作用域
@EnableAsync //开启异步也就是启动线程
public class ExcelTaskExecutorConfig implements AsyncConfigurer {
private static final Logger logger = LoggerFactory.getLogger(ExcelTaskExecutorConfig.class);
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(15); //最大线程数
taskExecutor.setCorePoolSize(10);
taskExecutor.setQueueCapacity(30);
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> logger.error("Async Exception:", throwable);
}
}
2.使用,这里注意两问题,
a.如果async和transaction同时注解在Service方法里,会出现拿不到spring的bean,解决方法看 Task1
b.如果是分开使用,就没有问题 Task2
@Service
@EnableAspectJAutoProxy(exposeProxy = true) //开启代理
public class Task1 {
//最大线程处理的数据量
private final int PAGE_SIZE = 400;
//并发计数
private AtomicInteger count;
@Async
public void batchUpdate() throws Exception {
List<XXX> list = testService.getList();
int total = list.size();
int pageTotal = getPageTotal(total);
count = new AtomicInteger(0);
TestService task = (TestService) AopContext.currentProxy(); //service的方法只能通过代理拿到
for (int i = 0; i < pageTotal; i++) {
List<XXX> pageList = list.stream().skip(i * PAGE_SIZE).limit(PAGE_SIZE).collect(Collectors.toList());
task.doData1(pageList,count);
}
}
private int getPageTotal(int dataSize) {
int pageTotal = 0;
if (dataSize == 0) {
return pageTotal;
}
if (dataSize % PAGE_SIZE == 0) {
pageTotal = dataSize / PAGE_SIZE;
} else {
pageTotal = dataSize / PAGE_SIZE + 1;
}
return pageTotal;
}
}
@Service
public class Task2 {
//最大线程处理的数据量
private final int PAGE_SIZE = 400;
//并发计数
private AtomicInteger count;
@Autowired
private TestService testService;
@Async
public void batchUpdate() throws Exception {
List<XXX> list = testService.getList();
int total = list.size();
int pageTotal = getPageTotal(total);
count = new AtomicInteger(0);
for (int i = 0; i < pageTotal; i++) {
List<XXX> pageList = list.stream().skip(i * PAGE_SIZE).limit(PAGE_SIZE).collect(Collectors.toList());
testService.doData2(pageList,count);
}
}
private int getPageTotal(int dataSize) {
同上
}
}
@Service
public class TestService{
private ReentrantLock lock = new ReentrantLock();
public List<XXX> getList(){
...
}
@Async
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Override
public void doData1(List<XXX> list,AtomicInteger count){
... 处理数据,更新、添加、想干嘛干嘛
//更新进度
lock.lock();
try {
int size = count.addAndGet(list.size());
double hand = 100D;
double percent = (double) size / (double) total * hand;
String remark = "处理多少:" + size + ",总共:" + total;
//更新进度 到数据库
} finally {
lock.unlock();
}
}
@Async
@Override
public void doData2(List<XXX> list,AtomicInteger count){
...同上
..这里如果更新,添加需要到具体的Service中添加事务注解
}
}