【问题标题】:Make thread sleep until a set date?让线程休眠直到设定的日期?
【发布时间】:2020-02-15 16:07:03
【问题描述】:

我想知道如何让线程休眠直到设定日期,例如设定日期 2020 年 2 月 14 日。

在此日期之前线程将保持休眠状态。有没有办法在java中做到这一点?。

【问题讨论】:

标签: java multithreading sleep


【解决方案1】:

执行者服务

定义一个Runnable(或Callable)。这意味着只需使用run 方法来遵守接口的约定。

在 lambda 语法中:

Runnable runnable =
    () -> { 
        System.out.println( "Looking up fresh stock prices at " + Instant.now().toString() ) ; 
    } 
;

接下来,学习现代 Java 中内置的 Executors 框架。见Oracle Tutorial。这个框架极大地简化了线程调度工作的棘手工作。

具体来说,您想使用ScheduledExecutorService。该接口用于调度任务在特定时间运行一次(实际上是在特定延迟到期后运行一次),重复运行一个任务。你当然想要前者。

Executors 类中获取一个实现。为了您的需要,我们只需要一个单线程。在其他情况下,您可能需要使用线程池。

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;

指定等待多长时间,延迟,直到任务被执行。计算等待所需的经过时间。

指定您的目标日期。在实际工作中,我会验证日期确实在未来。

LocalDate localDate = LocalDate.of( 2020 , Month.FEBRUARY , 23 ) ;

我们需要一个特定的时刻,而不仅仅是一个日期。我想你会想要那天的第一刻。不要假设这是 00:00。在某些日期的某些区域中的某些日子可能会从另一个时间开始,例如 01:00。始终让 java.time 确定第一时刻。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = localDate.atStartOfDay( z ) ;

从那个时区转换为 UTC。

Instant then = zdt.toInstant() ;

以 UTC 格式捕捉当前时刻。

Instant now = Instant.now() ;

将经过的时间计算为Duration

Duration d = Duration.between( now , then ) ;

现在安排我们的任务在延迟到期后运行。我建议增加一点时间,以确保任何相关系统的所有时钟都顺利进入新的一天。加上午夜往往是计算的Witching Hour,有许多 cron 作业、日志滚动、实用程序和报告运行。也许增加几分钟或更长时间。

ses.scheduleWithFixedDelay( runnable , d.plusMinutes( 7 ).toMinutes() , TimeUnit.MINUTES);

您可以选择捕获返回的ScheduledFuture 来监控您的任务。

重要提示请务必在不再需要或关闭应用程序时正常关闭执行程序服务。否则,您的线程可能会在您的应用退出后继续在后台运行。

ses.shutdown() ;

【讨论】:

    【解决方案2】:

    您可以使用 System.currentTimeMillis 获取当前日期,获取给定日期(在您的情况下为 2 月 14 日)的毫秒数,计算当前日期与给定日期之间的毫秒数,然后调用 sleep() 方法有了这个值。老实说,我不确定这有什么实际用途。

    这里有一个快速的解决方案:

     public static void main(String[] args) {
        long currentMillis = System.currentTimeMillis();
        long givenDateMillis = LocalDateTime.of(2020, 2, 14, 0, 0, 0)
                .atZone(ZoneId.systemDefault())
                .toInstant()
                .toEpochMilli();
    
        Thread.sleep(givenDateMillis - currentMillis);
    }
    

    我不建议在任何生产代码中使用它,对于这种情况,我建议使用某种调度程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-10
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 2011-05-14
      • 2011-01-03
      相关资源
      最近更新 更多