繁体   English   中英

Spring Boot 中的多线程 cron 作业

[英]Multithreading cron jobs in Spring Boot

我正在开发一个 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 ,第二次运行应使用 ID 11 到 20,依此类推,第 11 次运行应再次使用 ID 1 到 10,然后该过程继续。

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

我建议您异步执行 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);
        }
    }
}

创建一个包含 cron 作业逻辑的processor类:

@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 作业的执行将花费几毫秒,并且一个单独的线程(实际上将执行该作业)将在需要时运行。

但或许,您想要在单独的线程中执行每个关键字的搜索,但这是另一回事。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM