这是我第一次在Spring启动中使用Async。这是我的项目的结构。
我有以下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");
}
}
即使我在ExecutorConfig
类中设置了10个固定线程,看起来一次只能工作一个线程。知道我在做什么错吗?
答案 0 :(得分:3)
我想您的代码中有些事情并不完全正确。
AsyncConfigurer
@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 {}