每次迭代都为任务安排一个新的日期-JavaSpring
每次执行任务时,我都需要安排一个新的日期。 我见过许多例子,其中周期或间隔是由毫秒设置的,并且在每次迭代中都保持不变,但我找不到任何一个周期或间隔为下一次执行使用日期参数 我尝试了@Scheduled注释,因为我正在使用Spring,但我不知道是否有可能传递参数 我见过的例子 例1:每次迭代都为任务安排一个新的日期-JavaSpring,java,spring-boot,task,schedule,Java,Spring Boot,Task,Schedule,每次执行任务时,我都需要安排一个新的日期。 我见过许多例子,其中周期或间隔是由毫秒设置的,并且在每次迭代中都保持不变,但我找不到任何一个周期或间隔为下一次执行使用日期参数 我尝试了@Scheduled注释,因为我正在使用Spring,但我不知道是否有可能传递参数 我见过的例子 例1: @Scheduled(fixedRate = 20000) public void scheduler() { log.info("scheduler"); log.info
@Scheduled(fixedRate = 20000)
public void scheduler() {
log.info("scheduler");
log.info("Current Thread " + Thread.currentThread().getName());
log.info("Current Thread " + Thread.currentThread().getId());
}
例2:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(myRunnable, 10, 10, TimeUnit.MINUTES);
我希望从db表中读取一个日期,以便为新的迭代安排我的任务
谢谢你的帮助
编辑
注意:还有一段时间我需要决定在哪里停止下一次迭代,因此我尝试通过方法调用调度任务您可以注册一个新的
TimerTask
,执行所需逻辑,并在所需逻辑完成时注册一个新的TimerTask
:
public class Starter {
public void execute() {
Timer timer = new Timer();
Date firstExecutionDate = // ... compute ...
timer.schedule(
new RepeatedTimerTask(timer, this::toDoUponEachExecution, this::findNextExecutionDate),
firstExecutionDate
);
}
private Date findNextExecutionDate() {
// ... compute ...
}
private void toDoUponEachExecution() {
// ... do something ...
}
}
public class RepeatedTimerTask extends TimerTask {
private final Timer timer;
private final Runnable logic;
private final Supplier<Date> nextExecution;
public RepeatedTimerTask(Timer timer, Runnable logic, Supplier<Date> nextExecution) {
this.timer = timer;
this.logic = logic;
this.nextExecution = nextExecution;
}
@Override
public void run() {
logic.run();
timer.schedule(this, nextExecution.get());
}
}
公共类初学者{
public void execute(){
定时器=新定时器();
Date firstExecutionDate=/…计算。。。
时间表(
新的RepeatedTimerTask(计时器,this::ToDouponeAcheExecution,this::findNextExecutionDate),
首次处决日期
);
}
私有日期findNextExecutionDate(){
//…计算。。。
}
私有void toDoUponEachExecution(){
//…做点什么。。。
}
}
公共类RepeatedTimerTask扩展TimerTask{
私人最终定时器;
私有最终可运行逻辑;
私人最终供应商nextExecution;
公共RepeatedTimerTask(计时器、可运行逻辑、供应商下一步执行){
this.timer=计时器;
这个逻辑=逻辑;
this.nextExecution=nextExecution;
}
@凌驾
公开募捐{
logic.run();
timer.schedule(this,nextExecution.get());
}
}
我避免使用Spring,因此我无法在这方面帮助您。但是我可以通过使用ScheduledExecutorService
来指导您实现目标
ScheduledExecutorService::schedule(可运行命令、长延迟、时间单位)
您在以下方面部分是正确的:其三种调度策略中的两种设计用于在运行之间保持定期间隔:
Runnable
任务
Runnable runnable = new Runnable() {
@Override
public void run ( ) {
// Do the work of this task.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.systemDefault() ); // Capture the current moment.
System.out.println( "Current moment: " + zdt ); // Report the current moment.
// Schedule the next run of this task.
scheduledExecutorService.schedule( this , 10L , TimeUnit.SECONDS ); // Delay will not be *exactly* this amount of time due to interruptions of scheduling cores on CPU and threads by the JVM and host OS.
}
};
然后运行它
// Jump-start this perpetual motion machine.
scheduledExecutorService.schedule( runnable , 0L , TimeUnit.SECONDS ); // Start immediately, no delay.
让执行者在一定时间内重复执行其工作。当executor服务在后台线程上运行时,休眠主线程
请记住始终关闭执行器。否则,其后台线程可能会在主应用程序退出后很长时间内继续运行
scheduledExecutorService.shutdown();
System.out.println( "INFO - Executor shutting down. App exiting. " + ZonedDateTime.now( ZoneId.systemDefault() ) );
提示:始终将您的Runnable
代码包装在所有异常的try-catch中。到达executor服务的任何未捕获异常都将导致executor立即停止,并静默停止
Runnable runnable = new Runnable() {
@Override
public void run ( ) {
try {
// Do the work of this task.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.systemDefault() ); // Capture the current moment.
System.out.println( "Current moment: " + zdt ); // Report the current moment.
// Schedule the next run of this task.
scheduledExecutorService.schedule( this , 10L , TimeUnit.SECONDS ); // Delay will not be *exactly* this amount of time due to interruptions of scheduling cores on CPU and threads by the JVM and host OS.
} catch ( Exception e ) {
// TODO: Handle unexpected exeption.
System.out.println( "ERROR - unexpected exception caught on its way to reaching a scheduled executor service. Message # 55cbae82-8492-4638-9630-60c5b28ad876." );
}
}
};
我希望从db表中读取一个日期,以便为新的迭代安排我的任务
切勿使用日期
或日历
。几年前,随着JSR310的采用,java.time取代了那些糟糕的类
从JDBC4.2及更高版本开始,我们可以直接与数据库交换java.time对象
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC ) ;
OffsetDateTime later = myResultSet.getObject( … , OffsetDateTime.class ) ;
if( ! now.isBefore( later ) ) { … } // Verify the future moment is indeed in the future.
计算已用时间,即我们希望延迟到下一次计划运行的时间量
Duration d = Duration.between( now , odt ) ;
long seconds = d.toSeconds() ; // Truncates any fractional second.
使用该秒数安排下一次跑步
scheduledExecutorService.schedule( this , seconds , TimeUnit.SECONDS );
因此,Runnable
现在看起来是这样的
Runnable runnable = new Runnable() {
@Override
public void run ( ) {
try {
// Do the work of this task.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.systemDefault() ); // Capture the current moment.
System.out.println( "Current moment: " + zdt ); // Report the current moment.
// Schedule the next run of this task.
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC ) ;
… do your database query …
OffsetDateTime later = myResultSet.getObject( … , OffsetDateTime.class ) ;
if( ! now.isBefore( later ) ) { … } // Verify the future moment is indeed in the future.
Duration d = Duration.between( now , odt ) ;
long seconds = d.toSeconds() ; // Truncates any fractional second.
scheduledExecutorService.schedule( this , seconds , TimeUnit.SECONDS ); // Delay will not be *exactly* this amount of time due to interruptions of scheduling cores on CPU and threads by the JVM and host OS.
} catch ( Exception e ) {
// TODO: Handle unexpected exeption.
System.out.println( "ERROR - unexpected exception caught on its way to reaching a scheduled executor service. Message # 55cbae82-8492-4638-9630-60c5b28ad876." );
}
}
};
下面是一个完整的示例,它位于一个.java
文件中,但没有数据库查询
package work.basil.example;
import java.util.concurrent.*;
import java.time.*;
public class ScheduleNextTaskExample {
public static void main ( String[] args ) {
ScheduleNextTaskExample app = new ScheduleNextTaskExample();
app.doIt();
}
private void doIt ( ) {
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
@Override
public void run ( ) {
try {
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.systemDefault() ); // Capture the current moment.
System.out.println( "Current moment: " + zdt ); // Report the current moment.
scheduledExecutorService.schedule( this , 10L , TimeUnit.SECONDS ); // Delay will not be *exactly* this amount of time due to interruptions of scheduling cores on CPU and threads by the JVM and host OS.
} catch ( Exception e ) {
// TODO: Handle unexpected exeption.
System.out.println( "ERROR - unexpected exception caught on its way to reaching a scheduled executor service. Message # 55cbae82-8492-4638-9630-60c5b28ad876." );
}
}
};
// Jump-start this perpetual motion machine.
scheduledExecutorService.schedule( runnable , 0L , TimeUnit.SECONDS ); // Start immediately, no delay.
try {
Thread.sleep( TimeUnit.MINUTES.toMillis( 2 ) ); // Let our app, and the executor, run for 2 minutes, then shut them both down.
} catch ( InterruptedException e ) {
e.printStackTrace();
}
scheduledExecutorService.shutdown();
System.out.println( "INFO - Executor shutting down. App exiting. " + ZonedDateTime.now( ZoneId.systemDefault() ) );
}
}
定时器的使用几乎被计算机淘汰了。尤其是在Servlet或Jakarta EE环境中。此处显示的计划下一次运行方法也可以由执行者完成。请在此处检查接受的答案:
Runnable runnable = new Runnable() {
@Override
public void run ( ) {
try {
// Do the work of this task.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.systemDefault() ); // Capture the current moment.
System.out.println( "Current moment: " + zdt ); // Report the current moment.
// Schedule the next run of this task.
OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC ) ;
… do your database query …
OffsetDateTime later = myResultSet.getObject( … , OffsetDateTime.class ) ;
if( ! now.isBefore( later ) ) { … } // Verify the future moment is indeed in the future.
Duration d = Duration.between( now , odt ) ;
long seconds = d.toSeconds() ; // Truncates any fractional second.
scheduledExecutorService.schedule( this , seconds , TimeUnit.SECONDS ); // Delay will not be *exactly* this amount of time due to interruptions of scheduling cores on CPU and threads by the JVM and host OS.
} catch ( Exception e ) {
// TODO: Handle unexpected exeption.
System.out.println( "ERROR - unexpected exception caught on its way to reaching a scheduled executor service. Message # 55cbae82-8492-4638-9630-60c5b28ad876." );
}
}
};
package work.basil.example;
import java.util.concurrent.*;
import java.time.*;
public class ScheduleNextTaskExample {
public static void main ( String[] args ) {
ScheduleNextTaskExample app = new ScheduleNextTaskExample();
app.doIt();
}
private void doIt ( ) {
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
@Override
public void run ( ) {
try {
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.systemDefault() ); // Capture the current moment.
System.out.println( "Current moment: " + zdt ); // Report the current moment.
scheduledExecutorService.schedule( this , 10L , TimeUnit.SECONDS ); // Delay will not be *exactly* this amount of time due to interruptions of scheduling cores on CPU and threads by the JVM and host OS.
} catch ( Exception e ) {
// TODO: Handle unexpected exeption.
System.out.println( "ERROR - unexpected exception caught on its way to reaching a scheduled executor service. Message # 55cbae82-8492-4638-9630-60c5b28ad876." );
}
}
};
// Jump-start this perpetual motion machine.
scheduledExecutorService.schedule( runnable , 0L , TimeUnit.SECONDS ); // Start immediately, no delay.
try {
Thread.sleep( TimeUnit.MINUTES.toMillis( 2 ) ); // Let our app, and the executor, run for 2 minutes, then shut them both down.
} catch ( InterruptedException e ) {
e.printStackTrace();
}
scheduledExecutorService.shutdown();
System.out.println( "INFO - Executor shutting down. App exiting. " + ZonedDateTime.now( ZoneId.systemDefault() ) );
}
}