开发者社区> 问答> 正文

Spring Boot中的多线程cron作业

我正在开发一个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个关键字,最后一次获取其结果。因此,例如,第一次运行应使用keywordsID 1到10,第二次运行应使用ID 11到20,依此类推,第11次运行应再次使用ID 1到10,然后过程继续。

现在的问题是执行搜索要花费超过5分钟的时间。因此,尽管我已将cron作业设置为每5分钟运行一次,但直到第一次完成后才进行第二次运行。结果,完成搜索要花费数小时。我如何使该进程成为多线程,以便cron作业的多个实例可以同时运行,因为它们在不同的清单上运行keywords?

展开
收起
垚tutu 2019-11-29 22:58:11 982 0
1 条回答
写回答
取消 提交回答
  • #include

    我建议您使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;
        }   
    
        @
    S```  
    cheduled(cron = "* */5 * * * *")
        public void fetchLatestResults() throws Exception {
            yourCronJobExecutor.start(cronJobProcessor::executeYouCronJob);
        }
    }
    这样,您的cron作业的执行将花费几毫秒的时间,而实际上将执行作业的单独线程将在需要时运行。
    
    但是也许,您想在单独的线程中执行每个关键字的搜索,但这有点不同。
    2019-11-29 22:58:48
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载

相关实验场景

更多