简体   繁体   English

在 window 期间每 30 分钟运行一次任务

[英]Run a task every 30 min during time window

I am quite new to java, but I am trying to work out running a task every 30 min during the hours 5 AM to 5 PM during the week.我对 java 很陌生,但我试图在一周的上午 5 点到下午 5 点之间每 30 分钟运行一次任务。 I looked around and found that I could possible use this class我环顾四周,发现我可以使用这个 class

  ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

I am thinking I could use the library to call a function and wrap the function call in an if statement to check if it falls between the 9 to 5 time.我想我可以使用该库调用 function 并将 function 调用包装在 if 语句中,以检查它是否介于 9 到 5 次之间。 My only issue about this is running a thread thru out the night while it is not doing anything.我唯一的问题是在没有做任何事情的情况下通宵运行一个线程。 Was wondering if that is something I should worry about or is there a way I can just have the thread sleep after its last run for 8 or so hours until the next day想知道这是否是我应该担心的事情,或者有没有办法让线程在最后一次运行后休眠 8 个小时左右,直到第二天

Yes, use a ScheduledExecutorService .是的,使用ScheduledExecutorService

Notice how the schedule method takes a pair of arguments for an amount and a granularity of an amount of time to wait before running the task.请注意schedule方法如何使用一对 arguments 在运行任务之前等待的时间量和粒度。

So when you start your app, see how long until when you want to start the first task.因此,当您启动您的应用程序时,请查看您想要启动第一个任务的时间。 Use DayOfWeek to see if the current moment is Monday-Friday.使用DayOfWeek查看当前时刻是否为周一至周五。 Check to see if the current LocalTime is between 5 AM to 5 PM.检查当前LocalTime是否在上午 5 点到下午 5 点之间。 Use ZonedDateTime to determine moments.使用ZonedDateTime确定时刻。

To get the next working day, add the ThreeTen-Extra library to your project to get its next-working-day temporal adjuster implementation.要获得下一个工作日,请将ThreeTen-Extra库添加到您的项目中,以获得其下一个工作日的时间调整器实现。 All this has been covered many times already on Stack Overflow.所有这些已经在 Stack Overflow 上多次介绍过。 So search to learn more and see example code.因此,搜索以了解更多信息并查看示例代码。

Something like this untested code.像这个未经测试的代码。 (Use at your own risk.) (使用风险自负。)

public Duration untilNextRun ( final ZoneId zoneId )
{
    // Calculate the amount to wait untli the next run of some task.
    // From Monday-Friday, 5 AM to 5 PM, we want to run every half-hour.
    // Outside those hours, we must wait until the next 5 AM starting time.

    Set < DayOfWeek > weekDays = EnumSet.of( DayOfWeek.MONDAY , DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY , DayOfWeek.THURSDAY , DayOfWeek.FRIDAY );
    LocalTime startTime = LocalTime.of( 5 , 0 );
    LocalTime stopTime = LocalTime.of( 17 , 0 );

    ZonedDateTime now = ZonedDateTime.now( zoneId );
    DayOfWeek currentDayOfWeek = now.getDayOfWeek();
    LocalDate currentDate = now.toLocalDate();
    LocalTime currentTime = now.toLocalTime();


    if ( weekDays.contains( currentDayOfWeek ) )
    {
        if ( currentTime.isBefore( startTime ) )
        {
            // On a weekday, but too early to start a regular 30-minute wait. Wait until 5 AM on this same date.
            ZonedDateTime zdt = ZonedDateTime.of( currentDate , startTime , zoneId );
            Duration duration = Duration.between( now.toInstant() , zdt.toInstant() );
            return Objects.requireNonNull( duration );
        } else if ( currentTime.isBefore( stopTime ) )
        {
            // On a weekday, within our working hours, so start a regular 30-minute wait.
            return Duration.ofMinutes( 30 );
        } else if ( ! currentTime.isBefore( stopTime ) )
        {
            // Too late in the day to start another 30-minute wait. So wait until the next non-weekend day.
            LocalDate nextWorkingLocalDate = currentDate.with( Temporals.nextWorkingDay() ) ;
            ZonedDateTime zdt = ZonedDateTime.of( nextWorkingLocalDate , startTime , zoneId );
            Duration duration = Duration.between( now.toInstant() , zdt.toInstant() );
            return Objects.requireNonNull( duration );
        } else
        {
            throw new IllegalStateException( "Should not have ever reached this point. Message # 7818816c-4b5c-47e3-a0a5-d7c8c999f071." );
        }
    } else
    {
        // Not on a weekday (on a weekend instead), so we cannot start another 30-minute wait. So wait until the next non-weekend day.
        LocalDate nextWorkingLocalDate = currentDate.with( Temporals.nextWorkingDay() ) ;
        ZonedDateTime zdt = ZonedDateTime.of( nextWorkingLocalDate , startTime , zoneId );
        Duration duration = Duration.between( now.toInstant() , zdt.toInstant() );
        return Objects.requireNonNull( duration );
    }
}

Try using that method.尝试使用该方法。

Duration duration = this.untilNextRun( ZoneId.of( "America/Los_Angeles" ) );

System.out.println( "ZonedDateTime.now(…) = " + ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) ) );
System.out.println( "duration = " + duration );

ZonedDateTime.now(…) = 2020-04-06T18:29:41.880591-07:00[America/Los_Angeles] ZonedDateTime.now(…) = 2020-04-06T18:29:41.880591-07:00[America/Los_Angeles]

duration = PT10H30M18.124981S持续时间 = PT10H30M18.124981S

To schedule your task on the scheduled executor service, convert the Duration to a number of minutes or seconds.要在计划的执行器服务上安排您的任务,请将Duration转换为分钟或秒数。

ses.schedule( task , duration.toSeconds() , TimeUnit.SECONDS ) ;

As part of that task's duties, it should schedule another execution of the task.作为该任务职责的一部分,它应该安排该任务的另一次执行。 If the moment when the task finishes is still within the target hours, schedule a delay of 30 minutes.如果任务完成的时刻仍在目标小时内,请安排 30 分钟的延迟。 If the finishing moment is outside the target, schedule with a delay long enough to take us up to the next starting target time.如果结束时刻在目标之外,请延迟足够长的时间来安排我们到下一个起始目标时间。 That longer delay might be overnight for MF, or over the weekend.对于 MF 来说,更长的延迟可能是一夜之间,或者是周末。

Define your task as a Runnable or Callable .将您的任务定义为RunnableCallable Something like this untried code.像这个未经验证的代码。

Runnable task = ( ) -> {
    System.out.println( "Task is running at " + Instant.now() );
    //  … do your work …
    // Schedule task to run again.
    ZoneId z = ZoneId.of( "America/Montreal" );
    Duration d = this.untilNextRun( z );
    ses.schedule( task , d , TimeUnit.SECONDS ));
};

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

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