Java 如何每天下午2点运行TimerTask?

Java 如何每天下午2点运行TimerTask?,java,timer,scheduled-tasks,Java,Timer,Scheduled Tasks,我想每天下午2点执行一项工作。我可以使用java.util.Timer的哪种方法来安排我的工作 运行2小时后,它将停止作业并重新安排到第二天下午2点。我发现最简单的方法是通过Windows中的任务调度器和Linux中的cron 然而,对于Java,请看一看 从他们的网站: Quartz是一个功能齐全的开源作业调度服务,可以 可以与任何JavaEE或Java集成,或与之一起使用 SE应用程序-从最小的独立应用程序到 最大的电子商务系统。石英可以用来制作简单的或 执行十次、数百次甚至更多次的复杂计划

我想每天下午2点执行一项工作。我可以使用
java.util.Timer
的哪种方法来安排我的工作


运行2小时后,它将停止作业并重新安排到第二天下午2点。

我发现最简单的方法是通过Windows中的任务调度器和Linux中的cron

然而,对于Java,请看一看

从他们的网站:

Quartz是一个功能齐全的开源作业调度服务,可以 可以与任何JavaEE或Java集成,或与之一起使用 SE应用程序-从最小的独立应用程序到 最大的电子商务系统。石英可以用来制作简单的或 执行十次、数百次甚至更多次的复杂计划 数以万计的工作;任务定义为标准的作业 Java组件,可以执行几乎任何您可能编写的程序 让他们去做。Quartz调度器包括许多企业级 功能,例如JTA事务和集群


您可以使用
Timer.schedule(TimerTask,Date firstTime,long period)
方法,将
firstTime
设置为今天下午2点,并将
时段设置为24小时:

从指定的时间开始,为重复的固定延迟执行计划指定的任务。随后的执行大约每隔一定的时间间隔进行,间隔为指定的时间段


您应该尝试使用scheduleAtFixedRate(这将重复您的任务)。您需要创建一个TimerTask对象,该对象将指定要运行的内容(在run()中)和运行的时间(scheduledExecutionTime)。scheduleAtFixedRate还允许您指定第一个执行日期

使用公共作废计划(TimerTask任务、首次日期、长周期)

要使任务在第二天再次重复,只需将period设置为86400000毫秒(即1天)


为什么不使用Spring的@Scheduled(cron=“0 14***”)呢。。秒、分钟、小时、天、月、星期几。V酷。您甚至可以为9:00到11:00指定9-11,或在最后一个参数中指定MON-FRI。 您也可以通过编程方式调用它,就像大多数Spring的情况一样,以防您想在运行时设置时间。 见此:-

添加一个示例

   @Scheduled(cron="0 0 14 * * *")
    public void customScheduler(){
        try{
            // do what ever you want to run repeatedly
        }catch(Exception e){
            e.printStackTrace();

        }
    }
另外,请使用@Component annotation对包含此项的类进行注释,并请在Application.java(类包含主方法)类中提供@EnableScheduling,以使spring知道您正在应用程序中使用taskscheduler。

到期:

Java5.0引入了Java.util.concurrent包和 其中的并发实用程序是ScheduledThreadPoolExecutor,它 是一个线程池,用于以给定的速率或时间重复执行任务 延迟它实际上是一个更通用的替代品 计时器/计时器任务组合,因为它允许多个服务线程, 接受各种时间单位,不需要子类化TimerTask (只需实现Runnable)。配置ScheduledThreadPoolExecutor 使用一个线程使其相当于计时器

因此(将此代码添加到类中):

private ScheduledExecutorService ScheduledExecutorService;
公共ScheduledSendLog(){
init();
}
公共空间销毁(){
this.scheduledExecutorService.shutdown();
}
私有void init(){
scheduledExecutorService=
Executors.newScheduledThreadPool(1);
System.out.println(“--ScheduledSendLog created”+LocalDateTime.now());
startSchedule(本地时间(02,00));
}
私有void startSchedule(本地时间-时间){
此.scheduledExecutorService.scheduleWithFixedDelay(()->{
System.out.println(Thread.currentThread().getName())+
“| scheduleWithFixedDelay |”+LocalDateTime.now());
//或者你想要的任何东西
},计算初始延迟秒(时间),
LocalTime.MAX.toSecondOfDay(),
时间单位(秒);
}
专用长时间计算初始延迟秒(本地时间时间){
int currSec=LocalTime.now().toSecondOfDay();
int atSec=atTime.toSecondOfDay();
返回(当前秒<当前秒)?
atSec-currSec:(LocalTime.MAX.toSecondOfDay()+atSec-currSec);
}  

这个问题和下面两个问题的大多数答案都假设每天的毫秒数总是相同的

然而,这是不正确的,因为白天的灯光节省和闰秒。 这意味着,如果您的服务存在多年,并且计时器的准确性很重要, 固定时间计时器不是您的选择

因此,我想介绍一个比
java.util.timer
更灵活的计时器的代码片段

包szx;
导入java.time.LocalDateTime;
导入java.time.ZoneId;
导入java.util.Date;
导入java.util.Timer;
导入java.util.TimerTask;
导入java.util.function.function;
公共类调度执行器{
public void scheduleTime(可运行任务、LocalDateTime firstTime、,
功能(下一次){
pendingTask=任务;
定期安排(第一次,下一次);
}
定期保护的无效计划(LocalDateTime firstTime,
功能(下一次){
新建计时器()。计划(新建计时器任务()){
@凌驾
公开募捐{
定期安排(nextTime.apply(首次),nextTime);
pendingTask.run();
}
},Date.from(firstTime.atZone(ZoneId.systemDefault()).toInstant());
}
私有易失性可运行pendingTask=null;
}
然后,您可以通过以下方式调用上述方法,每天下午2点执行作业

new ScheduledExecutor().scheduleRegularly(() -> {

    // do your task...

}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));

代码背后的基本思想是重新计算到下一个滴答声的剩余时间,并每次启动一个新计时器。

记住我得到了一个答案,但如何在2小时后停止任务并将其重新安排到第二天
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 2);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);

// every night at 2am you run your task
Timer timer = new Timer();
timer.schedule(new YourTask(), today.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); // period: 1 day
   @Scheduled(cron="0 0 14 * * *")
    public void customScheduler(){
        try{
            // do what ever you want to run repeatedly
        }catch(Exception e){
            e.printStackTrace();

        }
    }
private ScheduledExecutorService scheduledExecutorService;

    public ScheduledSendLog() {
        init();
    }

    public void destroy() {
        this.scheduledExecutorService.shutdown();
    }

    private void init() {
        scheduledExecutorService =
                Executors.newScheduledThreadPool(1);
        System.out.println("---ScheduledSendLog created " + LocalDateTime.now());
        startSchedule(LocalTime.of(02, 00));
    }


    private void startSchedule(LocalTime atTime) {
        this.scheduledExecutorService.scheduleWithFixedDelay(() -> {
                    System.out.println(Thread.currentThread().getName() +
                            " |  scheduleWithFixedDelay | " + LocalDateTime.now());
                    // or whatever you want
                }, calculateInitialDelayInSec(atTime),
                LocalTime.MAX.toSecondOfDay(),
                TimeUnit.SECONDS);
    }

    private long calculateInitialDelayInSec(LocalTime atTime) {
        int currSec = LocalTime.now().toSecondOfDay();
        int atSec = atTime.toSecondOfDay();
        return (currSec < atSec) ?
                atSec - currSec : (LocalTime.MAX.toSecondOfDay() + atSec - currSec);

    }  
new ScheduledExecutor().scheduleRegularly(() -> {

    // do your task...

}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));