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

使用ThreadPoolTaskExecutor在特定日期调用方法

吴安和
2023-03-14

我有一个方法希望使用Spring运行一次,它需要在给定的java.util上运行。日期(或LocalDateTime)。我计划将该方法应该执行的所有日期持久化到数据源。它应该异步运行。

一种方法是每天检查数据库中的日期,如果日期已过且尚未执行,则执行该方法。有没有更好的方法

我知道Spring提供了ThreadPoolTaskSchedulerThreadPool TaskExecutor。我正在查看TaskScheduler界面中的ScheduledFuture计划(可运行任务,日期开始时间)。我需要创建RunnableSpring托管bean来调用我的方法吗?或者有更简单的注释可以做到这一点吗?举个例子真的很有帮助。

(也看了这里。)

共有2个答案

拓拔骁
2023-03-14

查看@Scheduled注释。它可能会实现你想要的。

@Scheduled(cron="*/5 * * * * MON-FRI")
public void scheduledDateWork() {
    Date date = new Date(); //or use DAO call to look up date in database

    executeLogic(date);
}

克朗表达的例子来自另一个答案:

"0 0 * * * *" = the top of every hour of every day.
"*/10 * * * * *" = every ten seconds.
"0 0 8-10 * * *" = 8, 9 and 10 o'clock of every day.
"0 0/30 8-10 * * *" = 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.
"0 0 9-17 * * MON-FRI" = on the hour nine-to-five weekdays
"0 0 0 25 12 ?" = every Christmas Day at midnight
郎魁
2023-03-14

通过将计划日期外部化(到数据库),典型的计划实践(即基于cron的或固定的计划)不再适用。给定目标日期,您可以按如下方式准确地计划任务:

Date now = new Date();
Date next = ... get next date from external source ...
long delay = next.getTime() - now.getTime();
scheduler.schedule(Runnable task, delay, TimeUnit.MILLISECONDS);

剩下的就是创建一种有效的方法来调度每个新任务。下面有一个 TaskDispatcher 线程,它根据下一个 java.util.Date(您从数据库中读取)来调度每个任务。无需每天检查;此方法足够灵活,可以与存储在数据库中的任何计划方案一起使用。

接下来是说明该方法的工作代码。

使用的示例任务;在这种情况下,只是Hibernate一段固定的时间。当任务完成时,TaskDispatcher会通过Count下拉锁发出信号。

public class Task implements Runnable {

    private final CountDownLatch completion;
    public Task(CountDownLatch completion) {
        this.completion = completion;
    }

    @Override
    public void run() {
        System.out.println("Doing task");
        try {
            Thread.sleep(60*1000);  // Simulate the job taking 60 seconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        completion.countDown();     // Signal that the job is complete
    }

}

调度程序负责读取下一个计划日期的数据库,启动可运行的 ScheduledFuture 并等待任务完成。

public class TaskDispatcher implements Runnable {

    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private boolean isInterrupted = false;

    @Override
    public void run() {

        while (!isInterrupted) {

            Date now = new Date();

            System.out.println("Reading database for next date");
            Date next = ... read next data from database ...

            //Date next = new Date();   // Used as test
            //next.setTime(now.getTime()+10*1000); // Used as test

            long delay = next.getTime() - now.getTime();
            System.out.println("Scheduling next task with delay="+delay);

            CountDownLatch latch = new CountDownLatch(1);
            ScheduledFuture<?> countdown = scheduler.schedule(new Task(latch), delay, TimeUnit.MILLISECONDS);

            try {
                System.out.println("Blocking until the current job has completed");
                latch.await();
            } catch (InterruptedException e) {
                System.out.println("Thread has been requested to stop");
                isInterrupted = true;
            }
            if (!isInterrupted)
                System.out.println("Job has completed normally");
        }

        scheduler.shutdown();

    }

}

TaskDispatcher 的启动方式如下(使用 Spring Boot) - 像通常使用 Spring 一样启动线程:

@Bean
public TaskExecutor taskExecutor() {
    return new SimpleAsyncTaskExecutor(); // Or use another one of your liking
}

@Bean
public CommandLineRunner schedulingRunner(TaskExecutor executor) {
    return new CommandLineRunner() {
        public void run(String... args) throws Exception {
            executor.execute(new TaskDispatcher());
        }
    };
}

让我知道这种方法是否适用于您的用例。

 类似资料:
  • 问题内容: 我试图用不同的颜色在JCalendar中设置特定日期,具体取决于数据库中是否有针对该日期的计划,该日期在数据库中存储为“ yyyy-MM- dd”,我在这里看到过类似的帖子在stackOverflow上,但我无法使其正常工作。 我不确定“ component [day] .setBackground(Color.green)”的工作方式,以及如何将其设置为仅在数据库中已为其计划好的日期

  • 问题内容: 我想在的日期选择器中禁用特定的日期。 我正在使用CSS作为组件。 我要禁用的日期将根据组合中先前值的选择而动态更改。 我相信应该可以,尽管不确定。 我怎样才能做到这一点 ? 问题答案: 我假设您正在使用Angular-UI中的指令。该属性使您可以禁用某些日期(例如,周末)。看到这个笨蛋http://plnkr.co/edit/gGAU0L?p=preview 如果要基于选择动态禁用日期

  • 问题内容: 我正在尝试使用JQuery Ui禁用特定日期。但是,我没有运气,这是我的代码: 实例化datepicker对象 获取日历中要禁用的日期 它似乎没有用,我知道如何解决这个问题。干杯。 问题答案: 好像您在一个输入上调用了两次。很难遵循您的代码,但是如果您重新组织代码并删除第二个调用,那么一切都会正常进行:

  • 我有以下ThreadPoolTaskExecator2配置 在我的公共类AdminService中,我有两个方法。 void triggerJob() 布尔执行sql(字符串sql) 如何将ThreadPoolTaskExecutor插入triggerJob方法,以便在第一个方法中调用executeSql时创建新线程。 在triggerjob中,我有一个基于条件调用executeSql的循环。 我

  • 这可能很简单,但我无法获得所需的输出。 我正在使用下面这个简单的查询来获取一个项目编号的最新exp\u日期 第一次查询仅显示20年8月1日的以下结果 现在,我想筛选上述结果,以获得“特定”的最新exp\u日期(例如:20年8月1日),因此我将查询修改为: 但这给了我多行,如果我使用,它会获取所需的输出。 如何让过滤在这里为特定的工作?

  • 我做了一个表单来更新历史数据和一个子表单,用来检查结果!除了一个小问题外,一切都很好。