@Async注释创建线程,但是只有一个线程承担所有负载

时间:2018-10-23 04:27:36

标签: asynchronous spring-data-jpa

我需要将巨大的有效载荷持久保存到数据库。因此,我决定使用异步调用来保留一批记录。我通过使用@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.
......................................

在日志中,我看到只有一个线程正在运行,并且按顺序保留了一批记录。

为什么只有一个线程正在承担保持所有记录的负担。

我的方法不正确吗?

3 个答案:

答案 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);
}
}