当前位置: 首页 > 知识库问答 >
问题:

Spring Boot中的多线程cron作业

经昱
2023-03-14

我正在开发一个Spring Boot应用程序,它在给定的网站中查找给定的关键字,如果找到匹配项,就会删除这些网页。我正在编写一个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个关键字,在cron作业中,我首先列出了上次获取结果的最旧的10个关键字。因此,例如,第一次运行应该使用id 1到10的关键字,第二次运行应该使用id 11到20,依此类推,第11次运行应该再次使用id 1到10,并且该过程继续。

现在,问题是执行搜索需要的时间远远超过5分钟。所以,即使我将cron作业设置为每5分钟运行一次,第二次运行直到第一次完成才会发生。因此,完成搜索需要几个小时。我如何使这个过程多线程,以便cron作业的多个实例可以同时运行,因为它们在不同的关键字列表上运行?

共有1个答案

房子昂
2023-03-14

我建议您使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作业的逻辑:

@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作业的执行将需要几毫秒的时间,一个单独的线程将实际执行该作业,它将根据需要运行多长时间。

但是,也许你想在一个单独的线程中搜索每个关键字,但这有点不同。

 类似资料:
  • 我需要在Springboot中实现多线程,同时使用POST方法调用API。我根据一个SELECT查询从oracle数据库中提取记录,然后使用行映射器逐个遍历每个记录。在下一步中,我只调用一个方法将这些记录发送到API,以postmapping的形式发送这些记录并取回记录。 因为select查询一次可以返回10、20或100条记录。逐个调用每条记录并不理想。我在想我是否可以一次发送多个记录。我不知道

  • 错误[ACTIVE]执行线程:队列“weblogic.kernel.default(自调优)”的“33”-07.02.2014 11:37:20,360 request_id=9E32EFA6-1374-4B1C-99E9-326A3A256B88错误代码:99异步任务中的错误,延迟0: 本地异常堆栈:Exception[EclipseLink-4002](Eclipse Persistence

  • 我有4-5个工作线程处理大型消息队列。我还有另一段代码,它使用2-3个worker运行。我想在处理大型消息队列时阻止所有其他工作者。 我正在使用JDK6和Jms 编辑: 队列进程工作者从未终止。当没有消息时,它们阻塞队列。这些工作者由执行器线程池管理,如果我使用读写锁,其中一个工作者也会被阻塞。此外,如果使用循环屏障,那么我必须终止线程,以便重新传递阻塞的第二个进程。由于工作者是由线程池管理的,所

  • 问题内容: 我正在使用一个Java程序,该程序会在完成一些文件传输后发送电子邮件。我正在使用Eclipse对该程序进行编码。如何设置Cron作业以在特定时间执行此Java程序。另外我在项目中有各种jar文件。请建议 问题答案: r0ast3d有一个快速清晰的答案-我确实需要做更多的搜索才能完成每个步骤,所以我将详细介绍他的步骤: 编写一个shell脚本以使用必要的参数来调用Java程序。例: 用冒

  • 原子操作是否足够安全,可以在多线程应用程序中使用它,而不会导致竞争条件和其他并发问题?假设我们不担心可见性(我们从CPU读取/写入所有内容)。