栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Java 如何使用ScheduledExecutorService每天在特定时间运行某些任务?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java 如何使用ScheduledExecutorService每天在特定时间运行某些任务?

与当前的Java SE 8版本一样,它具有出色的日期时间API,与

java.time
使用
java.util.Calendarand
相比,可以更轻松地完成这些计算
java.util.Date

  • 使用此新API的日期时间类,即LocalDateTime
  • 使用ZonedDateTime类处理时区特定的计算,包括夏令时问题。你将在此处找到教程和示例。
    现在作为使用你的用例计划任务的示例示例:
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/Los_Angeles"));ZonedDateTime nextRun = now.withHour(5).withMinute(0).withSecond(0);if(now.compareTo(nextRun) > 0)    nextRun = nextRun.plusDays(1);Duration duration = Duration.between(now, nextRun);long initalDelay = duration.getSeconds();ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); scheduler.scheduleAtFixedRate(new MyRunnableTask(),    initalDelay,    TimeUnit.DAYS.toSeconds(1),    TimeUnit.SECONDS);

initalDelay
计算问调度延迟在执行
TimeUnit.SECONDS
。对于此用例,单位毫秒及以下的时差问题似乎可以忽略不计。但是你还是可以使用的
duration.toMillis()
,并
TimeUnit.MILLISECONDS
以毫秒为单位处理调度
computaions

而且

TimerTask
对此或
ScheduledExecutorService
更好吗?

NO:

ScheduledExecutorService
似乎比更好
TimerTask。StackOverflow
已经为你提供了答案。

从@PaddyD,

你仍然遇到问题,如果希望它在正确的本地时间运行,则需要每年重新启动两次。scheduleAtFixedRate不会削减它,除非你对全年相同的UTC时间感到满意。

确实如此,@ PaddyD已经给出了解决方法(给他+1),我提供了一个Java8日期时间API和的工作示例

ScheduledExecutorService
。使用守护程序线程很危险

class MyTaskExecutor{    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);    MyTask myTask;    volatile boolean isStopIssued;    public MyTaskExecutor(MyTask myTask$)     {        myTask = myTask$;    }    public void startExecutionAt(int targetHour, int targetMin, int targetSec)    {        Runnable taskWrapper = new Runnable(){ @Override public void run()  {     myTask.execute();     startExecutionAt(targetHour, targetMin, targetSec); }        };        long delay = computeNextDelay(targetHour, targetMin, targetSec);        executorService.schedule(taskWrapper, delay, TimeUnit.SECONDS);    }    private long computeNextDelay(int targetHour, int targetMin, int targetSec)     {        LocalDateTime localNow = LocalDateTime.now();        ZoneId currentZone = ZoneId.systemDefault();        ZonedDateTime zonedNow = ZonedDateTime.of(localNow, currentZone);        ZonedDateTime zonedNextTarget = zonedNow.withHour(targetHour).withMinute(targetMin).withSecond(targetSec);        if(zonedNow.compareTo(zonedNextTarget) > 0) zonedNextTarget = zonedNextTarget.plusDays(1);        Duration duration = Duration.between(zonedNow, zonedNextTarget);        return duration.getSeconds();    }    public void stop()    {        executorService.shutdown();        try { executorService.awaitTermination(1, TimeUnit.DAYS);        } catch (InterruptedException ex) { Logger.getLogger(MyTaskExecutor.class.getName()).log(Level.SEVERE, null, ex);        }    }}

注意:

  • MyTask
    是具有功能的接口
    execute
  • 在停止时
    ScheduledExecutorService
    ,请始终
    awaitTermination
    在调用后使用
    shutdown
    :始终有可能你的任务被卡死/死锁,并且用户将永远等待。
    我给Calender给出的上一个示例只是我提到的一个想法,避免了精确的时间计算和夏时制问题。根据@PaddyD的抱怨更新了解决方案


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/441925.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号