我需要将巨大的有效载荷持久保存到数据库。因此,我决定使用异步调用来保留一批记录。我通过使用@EnableAsync注释启用了异步处理。我还在下面的服务层方法上使用了@Async
@Async
@Transactional
public CompletableFuture<Boolean> insertRecords(List<Record> records) {
recordRepository.saveAll(records);
recordRepository.flush();
LOGGER.debug(Thread.currentThread().getName()+" -> inserting);
return CompletableFuture.completedFuture(Boolean.TRUE);
}
Above method is called from another service method
@Transactional
public void performSomeDB(InputStream is){
//perform another CRUD operation
processStream(is);
}
private void processStream(InputStream is){
//Read stream using JsonReader and load into a list
// record by record. Once the desired batch is met, pass the
// list to insertRecords
List<Record> records = new ArrayList<>();
List<CompletableFuture<Boolean>> statuses = new ArrayList<>();
while(stream has data){
records.add(record);
statuses.add(insertRecords(records);
}
System.out.println(statuses.size()); // It returns >1 based on the iterations.
上面添加的某些代码比实际代码更具象征性。
当我查看日志时,我看到statuss.size()返回的值> 1,这意味着产生了更多的线程。但是只有一个线程可用于持久化,并且每次迭代都按顺序运行。
http-nio-9090-exec-10 -> insert records
http-nio-9090-exec-10 -> insert records.
......................................
在日志中,我看到只有一个线程正在运行,并且按顺序保留了一批记录。
为什么只有一个线程正在承担保持所有记录的负担。
我的方法不正确吗?
答案 0 :(得分:0)
这是Async的魔术和一般概念。它可以分担全部负载,而不会生成多个线程。
答案 1 :(得分:0)
如果您使用的是Spring的Java配置,则您的config类需要实现AsyncConfigurer:
@Configuration
@EnableAsync
public class AppConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(50);
executor.setThreadNamePrefix("MyPool");
executor.initialize();
return executor;
}
}
您可以参考以下文档以了解更多详细信息:http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html
答案 2 :(得分:0)
对于@Async注释,自调用(从同一类中调用async方法)将无法正常工作。 您应该在单独的类中创建该方法,并使用此类的bean对象对其进行引用。
@Component
public class DbInserter {
@Async
@Transactional
public CompletableFuture<Boolean> insertRecords(List<Record> records) {
recordRepository.saveAll(records);
recordRepository.flush();
LOGGER.debug(Thread.currentThread().getName()+" -> inserting);
return CompletableFuture.completedFuture(Boolean.TRUE);
}
}