Spring async ConcurrentTaskExecutor не работает правильно? - PullRequest
0 голосов
/ 04 июня 2019

Я впервые работаю с Async в Spring boot.Вот как структурирован мой проект.

У меня есть следующий ExecutorConfig класс

@Configuration
@EnableAsync
public class ExecutorConfig {
    @Bean(name = "ConcurrentTaskExecutor")
    public Executor getAsyncExecutor() {
        return new ConcurrentTaskExecutor(Executors.newFixedThreadPool(10));
    }
}

Этот следующий класс, который будет вызываться с @Scheduled

@Component
public class RealtyTracCountyScraper {

    @Autowired
    StateScrapeQueueRepository stateScrapeQueueRepository;

    @Autowired
    CountyScrapeRepository countyScrapeRepository;

    @Autowired
    CountyScraper countyScraper;

    // @Scheduled(cron = "0 0 */3 * * *")
    @EventListener(ApplicationReadyEvent.class)
    public void scrapeCountyLinks() {
        System.out.println("Scrape county links ran!");
        try {
            List<String> stateLinks = stateScrapeQueueRepository.getStatesLinks("");

            for (int i = 0; i < stateLinks.size(); i++) {
                countyScraper.run(stateLinks.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("---------------------");
        }
    }

}

и этот класс, который вызывается из класса выше (это класс, который содержит многопоточный метод)

@Component
public class CountyScraper implements AsyncConfigurer {

    @Autowired
    StateScrapeQueueRepository stateScrapeQueueRepository;

    @Autowired
    CountyScrapeRepository countyScrapeRepository;

    @Async("ConcurrentTaskExecutor")
    public void run(String stateLink) {
        System.out.println("New thread");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Done");

    }
}

Несмотря на то, что я установил 10 фиксированных потоков в классе ExecutorConfig, он выглядит как одиннить работает одновременно.Есть идеи, что я делаю не так?

1 Ответ

3 голосов
/ 04 июня 2019

Я полагаю, что в вашем коде есть пара не совсем правильных вещей.

  1. Ваш компонент реализует AsyncConfigurer
  2. У вас нет @EnableScheduling

Ваш CountyScraper реализует интерфейс AsyncConfigurer. Приводит к 2 возможным проблемам. Первый - это настройка асинхронной обработки со значениями по умолчанию и использованием прокси на основе интерфейса вместо прокси на основе класса. Отсюда устранение @Async. Хотя последнее, кажется, не так, никто никогда не узнает.

На самом деле AsyncConfigurer должен быть реализован вашим ExecutorConfig.

@Configuration
@EnableAsync
@EnableScheduling
public class ExecutorConfig implements AsyncConfigurer {

    public Executor getAsyncExecutor() {
        return taskExecutor();
    }

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new TaskExecutor();
        taskExecutor.setCorePoolSize(10);
        return taskExecutor;
    }
}

Это настроит значение по умолчанию Executor, используемое для асинхронной обработки. Вместо ConcurrentTaskExecutor я использовал ThreadPoolTaskExecutor. Последний позволяет немного больше конфигурации и будет хорошо очищать потоки, когда Spring Boot завершает работу.

СОВЕТ: Если вы используете Spring Boot 2.1, вы можете отказаться от конфигурации TaskExecutor и заменить ее только на конфигурацию.

Теперь вы можете использовать простой @Async вместо того, чтобы явно называть исполнителя (который теперь потерпит неудачу, потому что он назван по-другому).

spring.task.execution.pool.core-size=10 # Default is 8

Ваша конфигурация становится

@Configuration
@EnableAsync
@EnableScheduling
public class ExecutorConfig {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...