【问题标题】:Multithreading cron jobs in Spring BootSpring Boot 中的多线程 cron 作业
【发布时间】:2020-03-24 19:06:55
【问题描述】:

我正在开发一个 Spring Boot 应用程序,该应用程序在给定网站中查找给定的keywords,如果找到匹配项,则将网页报废。我正在编写一个 cron 作业,每 5 分钟刷新一次结果,如下所示:

@Scheduled(cron = "* */5 * * * *")
public void fetchLatestResults() throws Exception {
    LOG.debug("Fetching latest results >>>");
    List<Keyword> keywords = keywordService.findOldestSearched10();
    keywordService.updateLastSearchDate(keywords);
    searchResultService.fetchLatestResults(keywords);
    LOG.debug("<<< Latest results fetched");
}

数据库有 100 个keywords,在 cron 作业中,我首先列出最后一次获取结果的最旧的 10 个关键字。因此,例如,第一次运行应使用 ID 为 1 到 10 的 keywords,第二次运行应使用 ids 11 到 20,依此类推,第 11 次运行应再次使用 ids 1 到 10,然后进程继续。

现在,问题是执行搜索需要的时间远远超过 5 分钟。因此,尽管我已将 cron 作业设置为每 5 分钟运行一次,但在第一次运行完成之前不会进行第二次运行。因此,完成搜索需要几个小时。如何使这个进程成为多线程的,以便 cron 作业的多个实例可以同时运行,因为它们在 keywords 的不同列表上运行?

【问题讨论】:

    标签: java multithreading spring-boot cron


    【解决方案1】:

    我建议您异步执行您的 cron 作业。

    创建 executor 类,该类将创建一个新线程来运行您的 cron 作业:

    @Component
    public class YourCronJobExecutor {
    
        private int threadsNumber = 10;
        private ExecutorService executorService;
    
        @PostConstruct
        private void init() {
            executorService = Executors.newFixedThreadPool(threadsNumber);
        }
    
        /**
         * Start.
         * @param runnable - runnable instance.
         */
        public void start(Runnable runnable) {
            try {
                executorService.execute(runnable);
            } catch (RejectedExecutionException e) {
                init();
                executorService.execute(runnable);
            }
        }
    }
    

    创建一个 processor 类,其中将包含您的 cron 作业的逻辑:

    @Component
    public class CronJobProcessor {
    
        //logger
        //autowired beans
    
        public void executeYouCronJob() {
            LOG.debug("Fetching latest results >>>");
            List<Keyword> keywords = keywordService.findOldestSearched10();
            keywordService.updateLastSearchDate(keywords);
            searchResultService.fetchLatestResults(keywords);
            LOG.debug("<<< Latest results fetched");
        }
    }
    

    最后,您的 cron 作业类将如下所示:

    @Component
    public class YourCronJobClass {
    
        private final YourCronJobExecutor yourCronJobExecutor;
    
        private final CronJobProcessor cronJobProcessor;
    
        @Autowired
        public PopulateCourseStateController(YourCronJobExecutor yourCronJobExecutor,
                                             CronJobProcessor cronJobProcessor) {
            this.yourCronJobExecutor = yourCronJobExecutor;
            this.cronJobProcessor = cronJobProcessor;
        }   
    
        @Scheduled(cron = "* */5 * * * *")
        public void fetchLatestResults() throws Exception {
            yourCronJobExecutor.start(cronJobProcessor::executeYouCronJob);
        }
    }
    

    通过这种方式,您的 cron 作业的执行将花费几毫秒,并且一个单独的线程,它实际上将执行该作业,它将在需要时运行。

    但也许,您希望在单独的线程中执行每个关键字的搜索,但那是另一回事。

    【讨论】:

    • 这完美运行并提高了性能。谢谢。
    猜你喜欢
    • 2020-08-05
    • 2018-06-07
    • 2021-07-10
    • 1970-01-01
    • 2014-11-02
    • 2021-02-27
    • 2019-03-09
    • 1970-01-01
    • 2021-11-07
    相关资源
    最近更新 更多