Asynchronous @异步注释正在创建线程,但只有一个线程承担所有负载

Asynchronous @异步注释正在创建线程,但只有一个线程承担所有负载,asynchronous,spring-data-jpa,Asynchronous,Spring Data Jpa,我需要将巨大的负载持久化到数据库。所以我决定使用异步调用来持久化一批记录。我使用@EnableAsync注释启用了异步处理。我还在服务层的一个方法上使用了@Async,如下所示 @Async @Transactional public CompletableFuture<Boolean> insertRecords(List<Record> records) { recordRepository.saveAll(records); recordRepos

我需要将巨大的负载持久化到数据库。所以我决定使用异步调用来持久化一批记录。我使用@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.      
在日志中,我只看到一个线程正在运行并按顺序保存一批记录

为什么只有一个线程承担了保存所有记录的负载


我的方法不正确吗?

这就是异步的魔力和一般思想。它在不生成多个线程的情况下共享全部负载。

如果使用Spring的Java配置,您的配置类需要实现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;
        }
    }

您可以参考下面的文档了解更多详细信息:

至于@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);
}
}
@组件
公共类数据库插入器{
@异步的
@交易的
公共完整未来插入记录(列表记录){
recordRepository.saveAll(记录);
recordRepository.flush();
LOGGER.debug(Thread.currentThread().getName()+“->插入);
返回CompletableFuture.completedFuture(Boolean.TRUE);
}
}

应用程序中的瓶颈似乎是数据库。如果这是真的,那么用更多的请求并行地访问它可能不会有帮助。尤其是当所有请求都访问同一个表和索引时,这只会创建锁争用。
@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);
}
}